This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Olena, a generic and efficient image processing platform".
The branch exp/smearing has been created
at 1935bc36690804e3ee07a7c2344538c9d80287c8 (commit)
- Log -----------------------------------------------------------------
No new revisions were added by this update.
-----------------------------------------------------------------------
hooks/post-receive
--
Olena, a generic and efficient image processing platform
* scribo/layout/internal/smearing/bbox2d.hh,
* scribo/layout/internal/smearing/classification.hh,
* scribo/layout/internal/smearing/crla.hh,
* scribo/layout/internal/smearing/draw_region.hh,
* scribo/layout/internal/smearing/labeling.hh,
* scribo/layout/smearing.hh,
* tests/layout/smearing-nontext.pbm,
* tests/layout/smearing-text.pbm,
* tests/layout/smearing.cc: New.
* tests/layout/Makefile.am: New target.
---
scribo/ChangeLog | 16 +
scribo/scribo/layout/internal/smearing/bbox2d.hh | 151 +++++++++
.../layout/internal/smearing/classification.hh | 147 +++++++++
scribo/scribo/layout/internal/smearing/crla.hh | 219 +++++++++++++
.../scribo/layout/internal/smearing/draw_region.hh | 121 +++++++
scribo/scribo/layout/internal/smearing/labeling.hh | 340 ++++++++++++++++++++
scribo/scribo/layout/smearing.hh | 223 +++++++++++++
scribo/tests/layout/Makefile.am | 10 +-
scribo/tests/layout/smearing-nontext.pbm | 5 +
.../alignment_3.pbm => layout/smearing-text.pbm} | Bin 12167 -> 11996 bytes
scribo/tests/layout/{xy_cut.cc => smearing.cc} | 19 +-
11 files changed, 1240 insertions(+), 11 deletions(-)
create mode 100644 scribo/scribo/layout/internal/smearing/bbox2d.hh
create mode 100644 scribo/scribo/layout/internal/smearing/classification.hh
create mode 100644 scribo/scribo/layout/internal/smearing/crla.hh
create mode 100644 scribo/scribo/layout/internal/smearing/draw_region.hh
create mode 100644 scribo/scribo/layout/internal/smearing/labeling.hh
create mode 100644 scribo/scribo/layout/smearing.hh
create mode 100644 scribo/tests/layout/smearing-nontext.pbm
copy scribo/tests/{img/alignment_3.pbm => layout/smearing-text.pbm} (95%)
copy scribo/tests/layout/{xy_cut.cc => smearing.cc} (78%)
diff --git a/scribo/ChangeLog b/scribo/ChangeLog
index 90de65c..b10317a 100644
--- a/scribo/ChangeLog
+++ b/scribo/ChangeLog
@@ -1,3 +1,19 @@
+2013-05-13 Guillaume Lazzara <z(a)lrde.epita.fr>
+
+ Add Smearing layout analysis algorithm.
+
+ * scribo/layout/internal/smearing/bbox2d.hh,
+ * scribo/layout/internal/smearing/classification.hh,
+ * scribo/layout/internal/smearing/crla.hh,
+ * scribo/layout/internal/smearing/draw_region.hh,
+ * scribo/layout/internal/smearing/labeling.hh,
+ * scribo/layout/smearing.hh,
+ * tests/layout/smearing-nontext.pbm,
+ * tests/layout/smearing-text.pbm,
+ * tests/layout/smearing.cc: New.
+
+ * tests/layout/Makefile.am: New target.
+
2013-04-26 Guillaume Lazzara <z(a)lrde.epita.fr>
* scribo/binarization/sauvola_ms_split.hh: Make use of all arguments.
diff --git a/scribo/scribo/layout/internal/smearing/bbox2d.hh b/scribo/scribo/layout/internal/smearing/bbox2d.hh
new file mode 100644
index 0000000..502e279
--- /dev/null
+++ b/scribo/scribo/layout/internal/smearing/bbox2d.hh
@@ -0,0 +1,151 @@
+// Copyright (C) 2013 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.
+
+/// \file
+///
+/// \brief 2D box class used in Smearing algorithm.
+
+/// FIXME: Use box2d ?
+
+#ifndef SCRIBO_LAYOUT_INTERNAL_SMEARING_BBOX2D_HH
+# define SCRIBO_LAYOUT_INTERNAL_SMEARING_BBOX2D_HH
+
+# include <mln/core/alias/point2d.hh>
+
+namespace scribo
+{
+
+ namespace layout
+ {
+
+ namespace internal
+ {
+
+ namespace smearing
+ {
+
+ using namespace mln;
+
+ //---------------------------
+ // Bounding box 2D
+ //---------------------------
+
+ class bbox2d
+ {
+ public:
+ bbox2d();
+
+ bbox2d(const unsigned n,
+ const point2d& pmin,
+ const point2d& pmax);
+
+ point2d& pmin();
+ const point2d& pmin() const;
+
+ point2d& pmax();
+ const point2d& pmax() const;
+
+ point2d pcenter() const;
+
+ unsigned bbox_number() const;
+
+ private:
+ unsigned n_;
+ point2d pmin_;
+ point2d pmax_;
+ };
+
+# ifndef MLN_INCLUDE_ONLY
+
+ inline
+ bbox2d::bbox2d()
+ : n_(0), pmin_(point2d(0, 0)), pmax_(point2d(0, 0))
+ {
+ }
+
+ inline
+ bbox2d::bbox2d(const unsigned n,
+ const point2d& pmin,
+ const point2d& pmax)
+ : n_(n), pmin_(pmin), pmax_(pmax)
+ {
+ }
+
+ inline
+ point2d&
+ bbox2d::pmin()
+ {
+ return pmin_;
+ }
+
+ inline
+ const point2d&
+ bbox2d::pmin() const
+ {
+ return pmin_;
+ }
+
+ inline
+ point2d&
+ bbox2d::pmax()
+ {
+ return pmax_;
+ }
+
+ inline
+ const point2d&
+ bbox2d::pmax() const
+ {
+ return pmax_;
+ }
+
+ inline
+ point2d
+ bbox2d::pcenter() const
+ {
+ point2d p(pmin_.row() + (pmax_.row() - pmin_.row()) / 2,
+ pmin_.col() + (pmax_.col() - pmin_.col()) / 2);
+
+ return p;
+ }
+
+ inline
+ unsigned
+ bbox2d::bbox_number() const
+ {
+ return n_;
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace scribo::layout::internal::smearing
+
+ } // end of namespace scribo::layout::internal
+
+ } // end of namespace scribo::layout
+
+} // end of namespace scribo
+
+#endif // ! SCRIBO_LAYOUT_INTERNAL_SMEARING_BBOX2D_HH
diff --git a/scribo/scribo/layout/internal/smearing/classification.hh b/scribo/scribo/layout/internal/smearing/classification.hh
new file mode 100644
index 0000000..32c2405
--- /dev/null
+++ b/scribo/scribo/layout/internal/smearing/classification.hh
@@ -0,0 +1,147 @@
+// Copyright (C) 2013 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.
+
+/// \file
+///
+/// \brief Routines used in scribo::layout::smearing
+
+#ifndef SCRIBO_LAYOUT_INTERNAL_SMEARING_CLASSIFICATION_HH
+# define SCRIBO_LAYOUT_INTERNAL_SMEARING_CLASSIFICATION_HH
+
+# include <mln/core/image/image2d.hh>
+# include <scribo/layout/internal/smearing/bbox2d.hh>
+
+
+namespace scribo
+{
+
+ namespace layout
+ {
+
+ namespace internal
+ {
+
+ namespace smearing
+ {
+
+ using namespace mln;
+
+
+ template<typename V>
+ void classify_component(const bbox2d& bbox,
+ V label,
+ image2d<V>& labeled_img);
+
+ template<typename V>
+ void compute_region_info(const image2d<bool>& input,
+ const image2d<V>& labeled_img,
+ const bbox2d& bbox,
+ float& brl,
+ float& tc);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ //---------------------------
+ // Classify component
+ //---------------------------
+
+ template<typename V>
+ inline
+ void classify_component(const bbox2d& bbox,
+ V label,
+ image2d<V>& labeled_img)
+ {
+ const unsigned id = bbox.bbox_number();
+ const point2d& pmin = bbox.pmin();
+ const point2d& pmax = bbox.pmax();
+ box2d b(pmin, pmax);
+ mln_piter_(box2d) p(b);
+
+ for_all(p)
+ {
+ V& pixel = labeled_img(p);
+ if (pixel == id)
+ pixel = label;
+ }
+ }
+
+ //---------------------------
+ // Compute region information
+ //---------------------------
+
+ template<typename V>
+ inline
+ void compute_region_info(const image2d<bool>& input,
+ const image2d<V>& labeled_img,
+ const bbox2d& bbox,
+ float& brl,
+ float& tc)
+ {
+ const unsigned id = bbox.bbox_number();
+ const point2d& pmin = bbox.pmin();
+ const point2d& pmax = bbox.pmax();
+
+ for (int i = pmin.row(); i <= pmax.row(); ++i)
+ {
+ for (int j = pmin.col(); j <= pmax.col(); ++j)
+ {
+ const unsigned label_pixel = labeled_img.at_(i, j);
+
+ if (label_pixel == id)
+ {
+ const bool pixel = input.at_(i, j);
+
+ if (pixel)
+ {
+ if (j > 0 && input.at_(i, j - 1) == 0)
+ ++tc;
+
+ int k = j + 1;
+ for (; input.at_(i, k); ++k);
+ brl += (k - j);
+
+ j = k;
+ }
+ }
+ }
+ }
+
+ if (tc == 0.0f)
+ tc = 1.0f;
+ }
+
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace scribo::layout::internal::smearing
+
+ } // end of namespace scribo::layout::internal
+
+ } // end of namespace scribo::layout
+
+} // end of namespace scribo
+
+#endif // ! SCRIBO_LAYOUT_INTERNAL_SMEARING_CLASSIFICATION_HH
diff --git a/scribo/scribo/layout/internal/smearing/crla.hh b/scribo/scribo/layout/internal/smearing/crla.hh
new file mode 100644
index 0000000..431ed79
--- /dev/null
+++ b/scribo/scribo/layout/internal/smearing/crla.hh
@@ -0,0 +1,219 @@
+// Copyright (C) 2013 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.
+
+/// \file
+///
+/// \brief Routines used in scribo::layout::smearing
+
+#ifndef SCRIBO_LAYOUT_INTERNAL_SMEARING_CRLA_HH
+# define SCRIBO_LAYOUT_INTERNAL_SMEARING_CRLA_HH
+
+#include <mln/core/image/image2d.hh>
+#include <mln/pw/all.hh>
+#include <mln/core/image/dmorph/image_if.hh>
+
+
+namespace scribo
+{
+
+ namespace layout
+ {
+
+ namespace internal
+ {
+
+ namespace smearing
+ {
+
+
+ using namespace mln;
+
+
+ template< typename V >
+ void horizontal_CRLA(const image2d<V>& input,
+ image2d<V>& output,
+ const unsigned threshold,
+ const V bound);
+
+ template< typename V >
+ void vertical_CRLA(const image2d<V>& input,
+ image2d<V>& output,
+ const unsigned threshold,
+ const V bound);
+
+ template< typename V >
+ void CRLA(const image2d<V>& input,
+ image2d<V>& output,
+ const unsigned hthreshold,
+ const unsigned hthreshold2,
+ const unsigned vthreshold,
+ const V bound);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ //---------------------------
+ // Horizontal CRLA
+ //---------------------------
+
+ template< typename V >
+ inline
+ void horizontal_CRLA(const image2d<V>& input,
+ image2d<V>& output,
+ const unsigned threshold,
+ const V bound)
+ {
+ unsigned count = 0;
+ unsigned nrows = input.nrows();
+ unsigned ncols = input.ncols();
+ V last_pixel_value = 0;
+
+ for (unsigned i = 0; i < nrows; ++i)
+ {
+ for (unsigned j = 0; j < ncols; ++j)
+ {
+ V current_pixel = input.at_(i, j);
+
+ if (current_pixel == 0)
+ {
+ if (last_pixel_value)
+ {
+ unsigned k = j + 1;
+ for (; input.at_(i, k) == 0 && (k < ncols); ++k);
+
+ count = k - j;
+ current_pixel = input.at_(i, k);
+
+ if (last_pixel_value == current_pixel &&
+ current_pixel <= bound &&
+ count < threshold)
+ for (unsigned l = j; l <= k; ++l)
+ output.at_(i, l) = last_pixel_value;
+
+ j = k;
+ output.at_(i, j) = current_pixel;
+ last_pixel_value = current_pixel;
+ }
+ }
+ else
+ {
+ output.at_(i, j) = current_pixel;
+ last_pixel_value = current_pixel;
+ }
+ }
+ }
+ }
+
+ //---------------------------
+ // Vertical CRLA
+ //---------------------------
+
+ template< typename V >
+ inline
+ void vertical_CRLA(const image2d<V>& input,
+ image2d<V>& output,
+ const unsigned threshold,
+ const V bound)
+ {
+ unsigned count = 0;
+ unsigned nrows = input.nrows();
+ unsigned ncols = input.ncols();
+ V last_pixel_value = 0;
+
+ for (unsigned j = 0; j < ncols; ++j)
+ {
+ for (unsigned i = 0; i < nrows; ++i)
+ {
+ V current_pixel = input.at_(i, j);
+
+ if (current_pixel == 0)
+ {
+ if (last_pixel_value)
+ {
+ unsigned k = i + 1;
+ for (; !input.at_(k, j) && (k < nrows); ++k);
+
+ count = k - i;
+ current_pixel = input.at_(k, j);
+
+ if (last_pixel_value == current_pixel &&
+ current_pixel <= bound &&
+ count < threshold)
+ for (unsigned l = i; l <= k; ++l)
+ output.at_(l, j) = last_pixel_value;
+
+ i = k;
+ output.at_(i, j) = current_pixel;
+ last_pixel_value = current_pixel;
+ }
+ }
+ else
+ {
+ output.at_(i, j) = current_pixel;
+ last_pixel_value = current_pixel;
+ }
+ }
+ }
+ }
+
+ //---------------------------
+ // CRLA
+ //---------------------------
+
+ template< typename V >
+ inline
+ void CRLA(const image2d<V>& input,
+ image2d<V>& output,
+ const unsigned hthreshold,
+ const unsigned hthreshold2,
+ const unsigned vthreshold,
+ const V bound)
+ {
+ const box2d& domain = input.domain();
+ image2d<V> himg(domain);
+ image2d<V> vimg(domain);
+ data::fill(himg, 0);
+ data::fill(vimg, 0);
+
+ horizontal_CRLA(input, himg, hthreshold, bound);
+ vertical_CRLA(input, vimg, vthreshold, bound);
+
+ data::fill((output |(pw::value(himg) == pw::value(vimg))).rw(), pw::value(himg));
+
+ horizontal_CRLA(output, output, hthreshold2, bound);
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace scribo::layout::internal::smearing
+
+ } // end of namespace scribo::layout::internal
+
+ } // end of namespace scribo::layout
+
+} // end of namespace scribo
+
+#endif // ! SCRIBO_LAYOUT_INTERNAL_SMEARING_CRLA_HH
+
diff --git a/scribo/scribo/layout/internal/smearing/draw_region.hh b/scribo/scribo/layout/internal/smearing/draw_region.hh
new file mode 100644
index 0000000..ec1a415
--- /dev/null
+++ b/scribo/scribo/layout/internal/smearing/draw_region.hh
@@ -0,0 +1,121 @@
+// Copyright (C) 2013 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.
+
+/// \file
+///
+/// \brief Routines used in scribo::layout::smearing
+
+#ifndef SCRIBO_LAYOUT_INTERNAL_SMEARING_DRAW_REGION_HH
+# define SCRIBO_LAYOUT_INTERNAL_SMEARING_DRAW_REGION_HH
+
+# include <mln/core/image/image2d.hh>
+# include <scribo/layout/internal/smearing/bbox2d.hh>
+
+
+namespace scribo
+{
+
+ namespace layout
+ {
+
+ namespace internal
+ {
+
+ namespace smearing
+ {
+
+ using namespace mln;
+
+
+ template< typename V >
+ void remove_text_region(const bbox2d& bbox,
+ const image2d<bool>& input,
+ image2d<bool>& output,
+ image2d<V>& labeled_img_orig,
+ const image2d<V>& labeled_img);
+
+ template< typename V >
+ void draw_region(const bbox2d& bbox,
+ const image2d<bool>& input,
+ image2d<bool>& output,
+ image2d<V>& labeled_img);
+
+# ifndef MLN_INCLUDE_ONLY
+
+ template< typename V >
+ void remove_text_region(const bbox2d& bbox,
+ const image2d<bool>& input,
+ image2d<bool>& output,
+ image2d<V>& labeled_img_orig,
+ const image2d<V>& labeled_img)
+ {
+ const unsigned id = bbox.bbox_number();
+ box2d b(bbox.pmin(), bbox.pmax());
+ mln_piter_(box2d) p(b);
+
+ for_all(p)
+ {
+ const bool pixel = input(p);
+ const V label_pixel = labeled_img(p);
+
+ if (pixel && label_pixel == id)
+ {
+ output(p) = true;
+ labeled_img_orig(p) = 0;
+ }
+ }
+ }
+
+ template< typename V >
+ void draw_region(const bbox2d& bbox,
+ const image2d<bool>& input,
+ image2d<bool>& output,
+ image2d<V>& labeled_img)
+ {
+ const unsigned id = bbox.bbox_number();
+ box2d b(bbox.pmin(), bbox.pmax());
+ mln_piter_(box2d) p(b);
+
+ for_all(p)
+ {
+ const bool pixel = input(p);
+ const V label_pixel = labeled_img(p);
+
+ if (pixel && label_pixel == id)
+ output(p) = true;
+ }
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace scribo::layout::internal::smearing
+
+ } // end of namespace scribo::layout::internal
+
+ } // end of namespace scribo::layout
+
+} // end of namespace scribo
+
+#endif // ! SCRIBO_LAYOUT_INTERNAL_SMEARING_DRAW_REGION_HH
diff --git a/scribo/scribo/layout/internal/smearing/labeling.hh b/scribo/scribo/layout/internal/smearing/labeling.hh
new file mode 100644
index 0000000..bc55741
--- /dev/null
+++ b/scribo/scribo/layout/internal/smearing/labeling.hh
@@ -0,0 +1,340 @@
+// Copyright (C) 2013 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.
+
+/// \file
+///
+/// \brief Routines used in scribo::layout::smearing
+
+#ifndef SCRIBO_LAYOUT_INTERNAL_SMEARING_LABELING_HH
+# define SCRIBO_LAYOUT_INTERNAL_SMEARING_LABELING_HH
+
+#include <mln/core/image/image2d.hh>
+#include <scribo/layout/internal/smearing/bbox2d.hh>
+
+
+namespace scribo
+{
+
+ namespace layout
+ {
+
+ namespace internal
+ {
+
+ namespace smearing
+ {
+
+
+ using namespace mln;
+
+ struct labeling_position
+ {
+ labeling_position(const int x_, const int y_);
+ int x;
+ int y;
+ };
+
+
+ template< typename V >
+ void propagate(const labeling_position& position,
+ std::vector< labeling_position >& next_position_list,
+ const image2d<V>& input, image2d<unsigned>& labeled_image,
+ const unsigned nb_labels, bbox2d& bbox, const V value);
+
+
+ template< typename V >
+ void component_labeling(const image2d<V>& input,
+ unsigned& nb_labels,
+ std::vector<bbox2d>& bbox_list,
+ image2d<unsigned>& labeled_image,
+ const V bound);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+
+ //---------------------------
+ // Labeling position
+ //---------------------------
+
+ labeling_position::labeling_position(const int x_, const int y_)
+ : x(x_),
+ y(y_)
+ {
+ }
+
+ //---------------------------
+ // Propagate labeling
+ //---------------------------
+
+ template< typename V >
+ inline
+ void propagate(const labeling_position& position,
+ std::vector< labeling_position >& next_position_list,
+ const image2d<V>& input, image2d<unsigned>& labeled_image,
+ const unsigned nb_labels, bbox2d& bbox, const V value)
+ {
+ int x = position.x;
+ int y = position.y;
+ int nx;
+ int ny;
+ int ncols = input.ncols();
+ int nrows = input.nrows();
+
+ bool increment_xlr = false;
+ bool increment_ylr = false;
+ bool decrement_xul = false;
+ bool decrement_yul = false;
+
+ point2d& pmin = bbox.pmin();
+ point2d& pmax = bbox.pmax();
+ const int xul = pmin.col();
+ const int yul = pmin.row();
+ const int xlr = pmax.col();
+ const int ylr = pmax.row();
+
+ {
+ nx = x + 1;
+
+ if (nx < ncols)
+ {
+ unsigned& pixel = labeled_image.at_(y, nx);
+ if (input.at_(y, nx) == value && !pixel)
+ {
+ if (xlr < nx)
+ increment_xlr = true;
+ pixel = nb_labels;
+ next_position_list.push_back(labeling_position(nx, y));
+ }
+ }
+ }
+
+ {
+ nx = x + 1;
+ ny = y + 1;
+
+ if (nx < ncols && ny < nrows)
+ {
+ unsigned& pixel = labeled_image.at_(ny, nx);
+ if (input.at_(ny, nx) == value && !pixel)
+ {
+ if (xlr < nx)
+ increment_xlr = true;
+ if (ylr < ny)
+ increment_ylr = true;
+ pixel = nb_labels;
+ next_position_list.push_back(labeling_position(nx, ny));
+ }
+ }
+ }
+
+ {
+ ny = y + 1;
+
+ if (ny < nrows)
+ {
+ unsigned& pixel = labeled_image.at_(ny, x);
+ if (input.at_(ny, x) == value && !pixel)
+ {
+ if (ylr < ny)
+ increment_ylr = true;
+ pixel = nb_labels;
+ next_position_list.push_back(labeling_position(x, ny));
+ }
+ }
+ }
+
+ {
+ nx = x - 1;
+ ny = y + 1;
+
+ if (nx >= 0 && ny < nrows)
+ {
+ unsigned& pixel = labeled_image.at_(ny, nx);
+ if (input.at_(ny, nx) == value && !pixel)
+ {
+ if (xul > nx)
+ decrement_xul = true;
+ if (ylr < ny)
+ increment_ylr = true;
+ pixel = nb_labels;
+ next_position_list.push_back(labeling_position(nx, ny));
+ }
+ }
+ }
+
+ {
+ nx = x - 1;
+
+ if (nx >= 0)
+ {
+ unsigned& pixel = labeled_image.at_(y, nx);
+ if (input.at_(y, nx) == value && !pixel)
+ {
+ if (xul > nx)
+ decrement_xul = true;
+ pixel = nb_labels;
+ next_position_list.push_back(labeling_position(nx, y));
+ }
+ }
+ }
+
+ {
+ nx = x - 1;
+ ny = y - 1;
+
+ if (nx >= 0 && ny >= 0)
+ {
+ unsigned& pixel = labeled_image.at_(ny, nx);
+ if (input.at_(ny, nx) == value && !pixel)
+ {
+ if (xul > nx)
+ decrement_xul = true;
+ if (yul > ny)
+ decrement_yul = true;
+ pixel = nb_labels;
+ next_position_list.push_back(labeling_position(nx, ny));
+ }
+ }
+ }
+
+ {
+ ny = y - 1;
+
+ if (ny >= 0)
+ {
+ unsigned& pixel = labeled_image.at_(ny, x);
+ if (input.at_(ny, x) == value && !pixel)
+ {
+ if (yul > ny)
+ decrement_yul = true;
+ pixel = nb_labels;
+ next_position_list.push_back(labeling_position(x, ny));
+ }
+ }
+ }
+
+ {
+ nx = x + 1;
+ ny = y - 1;
+
+ if (nx < ncols && ny >= 0)
+ {
+ unsigned& pixel = labeled_image.at_(ny, nx);
+ if (input.at_(ny, nx) == value && !pixel)
+ {
+ if (xlr < nx)
+ increment_xlr = true;
+ if (yul > ny)
+ decrement_yul = true;
+ pixel = nb_labels;
+ next_position_list.push_back(labeling_position(nx, ny));
+ }
+ }
+ }
+
+ if (increment_xlr)
+ ++pmax.col();
+ if (increment_ylr)
+ ++pmax.row();
+ if (decrement_xul)
+ --pmin.col();
+ if (decrement_yul)
+ --pmin.row();
+ }
+
+ //---------------------------
+ // Component labeling
+ //---------------------------
+
+ template< typename V >
+ inline
+ void component_labeling(const image2d<V>& input,
+ unsigned& nb_labels,
+ std::vector<bbox2d>& bbox_list,
+ image2d<unsigned>& labeled_image,
+ const V bound)
+ {
+ std::vector<labeling_position> position_list;
+ std::vector<labeling_position> next_position_list;
+ unsigned nrows = input.nrows();
+ unsigned ncols = input.ncols();
+
+ next_position_list.reserve(8);
+
+ for (unsigned i = 0; i < nrows; ++i)
+ {
+ for (unsigned j = 0; j < ncols; ++j)
+ {
+ if (input.at_(i, j) && !labeled_image.at_(i, j))
+ {
+ V value = input.at_(i, j);
+
+ if (value <= bound)
+ {
+ ++nb_labels;
+ position_list.clear();
+ position_list.push_back(labeling_position(j, i));
+
+ labeled_image.at_(i, j) = nb_labels;
+
+ point2d p(i, j);
+ bbox2d bbox(nb_labels, p, p);
+
+ while (!position_list.empty())
+ {
+ unsigned nb_positions = position_list.size();
+ next_position_list.clear();
+
+ for (unsigned k = 0; k < nb_positions; ++k)
+ {
+ const labeling_position& position = position_list[k];
+
+ propagate(position, next_position_list, input,
+ labeled_image, nb_labels, bbox, value);
+ }
+
+ position_list.clear();
+ position_list = next_position_list;
+ }
+
+ bbox_list.push_back(bbox);
+ }
+ }
+ }
+ }
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace scribo::layout::internal::smearing
+
+ } // end of namespace scribo::layout::internal
+
+ } // end of namespace scribo::layout
+
+} // end of namespace scribo
+
+#endif // ! SCRIBO_LAYOUT_INTERNAL_SMEARING_LABELING_HH
diff --git a/scribo/scribo/layout/smearing.hh b/scribo/scribo/layout/smearing.hh
new file mode 100644
index 0000000..2574876
--- /dev/null
+++ b/scribo/scribo/layout/smearing.hh
@@ -0,0 +1,223 @@
+// Copyright (C) 2013 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.
+
+/// \file
+///
+/// \brief Smearing layout analysis algorithm.
+
+#ifndef SCRIBO_LAYOUT_SMEARING_HH
+# define SCRIBO_LAYOUT_SMEARING_HH
+
+# include <mln/core/image/image2d.hh>
+# include <mln/util/couple.hh>
+
+# include <scribo/layout/internal/smearing/crla.hh>
+# include <scribo/layout/internal/smearing/labeling.hh>
+# include <scribo/layout/internal/smearing/classification.hh>
+# include <scribo/layout/internal/smearing/draw_region.hh>
+
+
+namespace scribo
+{
+
+ namespace layout
+ {
+
+ using namespace mln;
+
+ /*! \brief The Smearing layout analysis algorithm. This algorithm
+ is an implementation according to paper \cite ogorman1993pami.
+
+ \param[in] A binary image.
+
+ \return A couple of binary images. The first one contains the
+ text components and the second one the non-text components.
+
+ \ingroup grpalgolayout
+ */
+ template <typename I>
+ util::couple<mln_concrete(I), mln_concrete(I)>
+ smearing(const Image<I>& input);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ template <typename I>
+ util::couple<mln_concrete(I), mln_concrete(I)>
+ smearing(const Image<I>& input_)
+ {
+ mln_trace("scribo::layout::smearing");
+
+ using namespace internal::smearing;
+
+ typedef mln_value(I) V;
+ mlc_is(V,bool)::check();
+
+ const I& input = exact(input_);
+ mln_precondition(input.is_valid());
+
+ //-------------------------
+ // Initialization
+ //-------------------------
+
+ const box2d& domain = input.domain();
+ image2d<bool> output_text(domain);
+ image2d<bool> output_non_text(domain);
+ data::fill(output_text, false);
+ data::fill(output_non_text, false);
+
+
+ //-------------------------
+ // Component labeling
+ //-------------------------
+
+ std::vector<bbox2d> bbox_list;
+ image2d<unsigned> labeled_img(domain);
+ data::fill(labeled_img, 0);
+ unsigned nlabels = 0;
+
+ internal::smearing::component_labeling(input, nlabels,
+ bbox_list, labeled_img, true);
+
+ //-------------------------
+ // Classification
+ //-------------------------
+
+ std::vector<bbox2d>::iterator it_begin = bbox_list.begin();
+ std::vector<bbox2d>::iterator it_end = bbox_list.end();
+
+ for (; it_begin != it_end; ++it_begin)
+ {
+ const bbox2d& bbox = (*it_begin);
+ const unsigned height = bbox.pmax().row() - bbox.pmin().row();
+ unsigned c = 0;
+
+ if (height < 120)
+ c = 1;
+ else if (height >= 120 && height < 360)
+ c = 2;
+ else
+ c = 3;
+
+ internal::smearing::classify_component(bbox, c, labeled_img);
+ }
+
+ //-------------------------
+ // First pass
+ //-------------------------
+
+ {
+ image2d<unsigned> output_CRLA(domain);
+ data::fill(output_CRLA, 0);
+ const unsigned bound = 1;
+
+ internal::smearing::CRLA(labeled_img, output_CRLA, 360, 15, 360, bound);
+
+ image2d<unsigned> f_labeled_img(domain);
+ data::fill(f_labeled_img, 0);
+ nlabels = 0;
+ bbox_list.clear();
+
+ internal::smearing::component_labeling(output_CRLA, nlabels,
+ bbox_list, f_labeled_img,
+ bound);
+
+ it_begin = bbox_list.begin();
+ it_end = bbox_list.end();
+
+ for (; it_begin != it_end; ++it_begin)
+ {
+ float brl = 0.0f;
+ float tc = 0.0f;
+ const bbox2d& bbox = (*it_begin);
+ const unsigned width = bbox.pmax().col() - bbox.pmin().col();
+
+ internal::smearing::compute_region_info(input, f_labeled_img,
+ bbox, brl, tc);
+
+ const float mbrl = brl / tc;
+ const float mtc = tc / width;
+
+ if (mbrl >= 0.4f && mbrl <= 15.0f && mtc >= 1.0f && mtc <= 3.8f)
+ internal::smearing::remove_text_region(bbox, input, output_text,
+ labeled_img, f_labeled_img);
+ }
+ }
+
+ //-------------------------
+ // Second pass
+ //-------------------------
+
+ {
+ image2d<unsigned> output_CRLA(domain);
+ data::fill(output_CRLA, 0);
+ const unsigned bound = 2;
+
+ internal::smearing::CRLA(labeled_img, output_CRLA, 360, 60, 360, bound);
+
+ image2d<unsigned> s_labeled_img(domain);
+ data::fill(s_labeled_img, 0);
+ nlabels = 0;
+ bbox_list.clear();
+
+ internal::smearing::component_labeling(output_CRLA, nlabels,
+ bbox_list, s_labeled_img,
+ bound);
+
+ it_begin = bbox_list.begin();
+ it_end = bbox_list.end();
+
+ for (; it_begin != it_end; ++it_begin)
+ {
+ float brl = 0.0f;
+ float tc = 0.0f;
+ const bbox2d& bbox = (*it_begin);
+ const unsigned width = bbox.pmax().col() - bbox.pmin().col();
+
+ internal::smearing::compute_region_info(input, s_labeled_img,
+ bbox, brl, tc);
+
+ const float mbrl = brl / tc;
+ const float mtc = tc / width;
+
+ if (mbrl >= 2.2f && mbrl <= 45.0f && mtc >= 1.2f && mtc <= 9.0f)
+ internal::smearing::draw_region(bbox, input, output_text,
+ s_labeled_img);
+ else
+ internal::smearing::draw_region(bbox, input, output_non_text,
+ s_labeled_img);
+ }
+ }
+
+ return mln::make::couple(output_text, output_non_text);
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace scribo::layout
+
+} // end of namespace scribo
+
+#endif // ! SCRIBO_LAYOUT_SMEARING_HH
diff --git a/scribo/tests/layout/Makefile.am b/scribo/tests/layout/Makefile.am
index 09990b1..0eab5d5 100644
--- a/scribo/tests/layout/Makefile.am
+++ b/scribo/tests/layout/Makefile.am
@@ -1,5 +1,4 @@
-# Copyright (C) 2013 EPITA Research and Development
-# Laboratory (LRDE).
+# Copyright (C) 2013 EPITA Research and Development Laboratory (LRDE).
#
# This file is part of Olena.
#
@@ -17,6 +16,11 @@
include $(top_srcdir)/scribo/tests/tests.mk
-check_PROGRAMS = xy_cut
+check_PROGRAMS = smearing \
+ xy_cut
+
+
+EXTRA_DIST = smearing-nontext.pbm \
+ smearing-text.pbm
TESTS = $(check_PROGRAMS)
diff --git a/scribo/tests/layout/smearing-nontext.pbm b/scribo/tests/layout/smearing-nontext.pbm
new file mode 100644
index 0000000..0bffbcf
--- /dev/null
+++ b/scribo/tests/layout/smearing-nontext.pbm
@@ -0,0 +1,5 @@
+P4
+# Generated by Milena 1.0 http://olena.lrde.epita.fr
+# EPITA Research and Development Laboratory (LRDE)
+436 216
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð
\ No newline at end of file
diff --git a/scribo/tests/img/alignment_3.pbm b/scribo/tests/layout/smearing-text.pbm
similarity index 95%
copy from scribo/tests/img/alignment_3.pbm
copy to scribo/tests/layout/smearing-text.pbm
index 89ec978..1975c01 100644
Binary files a/scribo/tests/img/alignment_3.pbm and b/scribo/tests/layout/smearing-text.pbm differ
diff --git a/scribo/tests/layout/xy_cut.cc b/scribo/tests/layout/smearing.cc
similarity index 78%
copy from scribo/tests/layout/xy_cut.cc
copy to scribo/tests/layout/smearing.cc
index 3601d64..d5185db 100644
--- a/scribo/tests/layout/xy_cut.cc
+++ b/scribo/tests/layout/smearing.cc
@@ -28,22 +28,25 @@
#include <iostream>
#include <mln/io/pbm/load.hh>
#include <mln/make/box2d.hh>
-#include <scribo/layout/xy_cut.hh>
+#include <mln/data/compare.hh>
+#include <scribo/layout/smearing.hh>
#include "tests/data.hh"
using namespace mln;
-int main(int argc, char** argv)
+int main()
{
image2d<bool> input;
io::pbm::load(input, SCRIBO_IMG_DIR "/alignment_3.pbm");
- util::array<box2d> bb = scribo::layout::xy_cut(input, 10, 10);
+ util::couple<image2d<bool>, image2d<bool> >
+ res = scribo::layout::smearing(input);
- mln_assertion(bb.nelements() == 4);
- mln_assertion(bb[0] == make::box2d(20,66, 38,140));
- mln_assertion(bb[1] == make::box2d(11,171, 38,221));
- mln_assertion(bb[2] == make::box2d(0,237, 38,384));
- mln_assertion(bb[3] == make::box2d(50,60, 215,402));
+ image2d<bool> ref1, ref2;
+ io::pbm::load(ref1, SCRIBO_TESTS_DIR "/layout/smearing-text.pbm");
+ io::pbm::load(ref2, SCRIBO_TESTS_DIR "/layout/smearing-nontext.pbm");
+
+ mln_assertion(ref1 == res.first());
+ mln_assertion(ref2 == res.second());
}
--
1.7.2.5
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Olena, a generic and efficient image processing platform".
The branch exp/values has been updated
discards cc5739adc63641001c47bb6c849519071a3f8cda (commit)
via f37b6039c9899c78f98ccd1e7ffa7eedb859a6df (commit)
via e9454b5c16ceb5d4cd662c4d9cde7ffd66d37596 (commit)
via 42c92be12e2271098726909965f6b103d4030114 (commit)
This update added new revisions after undoing existing revisions. That is
to say, the old revision is not a strict subset of the new revision. This
situation occurs when you --force push a change and generate a repository
containing something like this:
* -- * -- B -- O -- O -- O (cc5739adc63641001c47bb6c849519071a3f8cda)
\
N -- N -- N (f37b6039c9899c78f98ccd1e7ffa7eedb859a6df)
When this happens we assume that you've already had alert emails for all
of the O revisions, and so we here report only the revisions in the N
branch from the common base, B.
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
f37b603 NEWS: Add entry for labeling::values.
e9454b5 Regen auto-generated files.
42c92be mln/labeling/values.hh: Labeling algorithm for gray-level images.
-----------------------------------------------------------------------
Summary of changes:
ChangeLog | 4 +++
NEWS | 2 +
milena/ChangeLog | 12 +++++++++++
milena/headers.mk | 1 +
milena/mln/labeling/values.hh | 35 +++++++++++++++++----------------
milena/tests/unit_test/unit-tests.mk | 3 ++
6 files changed, 40 insertions(+), 17 deletions(-)
hooks/post-receive
--
Olena, a generic and efficient image processing platform