* lrde-upload.sh: Here.
Add a copyright header.
---
ChangeLog | 7 +++++++
lrde-upload.sh | 33 ++++++++++++++++++++++++++-------
2 files changed, 33 insertions(+), 7 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 953c68b..bd092e5 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2010-05-28 Roland Levillain <roland(a)lrde.epita.fr>
+
+ Add `swilena' to the branches to be uploaded.
+
+ * lrde-upload.sh: Here.
+ Add a copyright header.
+
2010-05-10 Roland Levillain <roland(a)lrde.epita.fr>
Upload only branches master and next, in their own directories.
diff --git a/lrde-upload.sh b/lrde-upload.sh
index 8a30466..436beb7 100755
--- a/lrde-upload.sh
+++ b/lrde-upload.sh
@@ -1,5 +1,22 @@
#! /bin/sh
+# Copyright (C) 2009, 2010 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/>.
+
+
# This file is run by the LRDE autobuilder after a successful compilation.
# It is not meant to be distributed with Olena.
@@ -14,19 +31,21 @@ set -ex
# | | `-- ...
# | |-- olena-$VERSION-snapshot-master-$date.tar.bz2
# | `-- olena-$VERSION-snapshot-master-$date.tar.gz
-# `-- next
-# |-- doc
-# | `-- milena
-# | `-- ...
-# |-- olena-$VERSION-snapshot-next-$date.tar.bz2
-# `-- olena-$VERSION-snapshot-next-$date.tar.gz
+# |-- next
+# | |-- doc
+# | | `-- milena
+# | | `-- ...
+# | |-- olena-$VERSION-snapshot-next-$date.tar.bz2
+# | `-- olena-$VERSION-snapshot-next-$date.tar.gz
+# ...
+#
# Buildbot will tell us the name of the branch being compiled using $1.
branch=$1
case "$branch" in
# Consider these branches only.
- master|next) ;;
+ master|next|swilena) ;;
# Don't upload other branches.
*) exit ;;
esac
--
1.5.6.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 fix-g++-4.2-strict-aliasing has been deleted
was 72a1d9cca4425b195b9132e2bd645274f52c765a
-----------------------------------------------------------------------
72a1d9cca4425b195b9132e2bd645274f52c765a Prevent g++ 4.2 from issuing bad code for graph-morpho/samples_image2d.
-----------------------------------------------------------------------
hooks/post-receive
--
Olena, a generic and efficient image processing platform
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 g++-3.3-compatibility has been deleted
was 81ebf3143f310e04f99738afb8b5ad9cbc39eaa7
-----------------------------------------------------------------------
81ebf3143f310e04f99738afb8b5ad9cbc39eaa7 Help g++ 3.3 compile Scribo code.
-----------------------------------------------------------------------
hooks/post-receive
--
Olena, a generic and efficient image processing platform
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 fix-lrde-upload has been deleted
was 68d80d9e1c6f2b66a45e6bb107c7697871386426
-----------------------------------------------------------------------
68d80d9e1c6f2b66a45e6bb107c7697871386426 Upload only the HTML version of the user reference manual.
-----------------------------------------------------------------------
hooks/post-receive
--
Olena, a generic and efficient image processing platform
---
scribo/ChangeLog | 4 ++
scribo/io/text_boxes/save.hh | 102 ++++++++++++++++++++++++++++++++++++++++++
2 files changed, 106 insertions(+), 0 deletions(-)
create mode 100644 scribo/io/text_boxes/save.hh
diff --git a/scribo/ChangeLog b/scribo/ChangeLog
index 623147b..fe1e390 100644
--- a/scribo/ChangeLog
+++ b/scribo/ChangeLog
@@ -1,5 +1,9 @@
2010-05-25 Guillaume Lazzara <z(a)lrde.epita.fr>
+ * io/text_boxes/save.hh: New. Save text boxes information.
+
+2010-05-25 Guillaume Lazzara <z(a)lrde.epita.fr>
+
Add a new deskew algorithm.
* preprocessing/deskew.hh,
diff --git a/scribo/io/text_boxes/save.hh b/scribo/io/text_boxes/save.hh
new file mode 100644
index 0000000..5bbf97b
--- /dev/null
+++ b/scribo/io/text_boxes/save.hh
@@ -0,0 +1,102 @@
+// Copyright (C) 2010 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_IO_TEXT_BOXES_SAVE_HH
+# define SCRIBO_IO_TEXT_BOXES_SAVE_HH
+
+/// \file
+///
+/// \brief Save text line information as XML.
+
+
+# include <fstream>
+# include <sstream>
+
+# include <scribo/core/line_set.hh>
+
+namespace scribo
+{
+
+ namespace io
+ {
+
+ namespace text_boxes
+ {
+
+ template <typename L>
+ void
+ save(const line_set<L>& lines,
+ const std::string& output_name,
+ const mln_site(L)& crop_shift = literal::origin);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+
+ template <typename L>
+ void
+ save(const line_set<L>& lines,
+ const std::string& output_name,
+ const mln_site(L)& crop_shift = literal::origin)
+ {
+ trace::entering("scribo::io::text_boxes:save");
+ mln_precondition(lines.is_valid());
+
+ std::ofstream file(output_name.c_str());
+ if (! file)
+ {
+ std::cerr << "error: cannot open file '" << output_name << "'!";
+ abort();
+ }
+
+ for_all_lines(l, lines)
+ {
+ if (! lines(l).is_valid() || lines(l).tag() != line::None || lines(l).type() != line::Text || lines(l).text().empty())
+ continue;
+
+ file << lines(l).bbox().pmin().row() + crop_shift.row()<< " "
+ << lines(l).bbox().pmin().col() + crop_shift.col()<< " "
+ << lines(l).bbox().pmax().row() + crop_shift.row() << " "
+ << lines(l).bbox().pmax().col() + crop_shift.col()<< " "
+ << lines(l).text() << std::endl;
+ }
+
+ file.close();
+
+
+ trace::exiting("scribo::io::text_boxes::save");
+ }
+
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace scribo::io::text_boxes
+
+ } // end of namespace scribo::io
+
+} // end of namespace scribo
+
+
+#endif // ! SCRIBO_IO_TEXT_BOXES_SAVE_HH
--
1.5.6.5
* preprocessing/deskew.hh,
* preprocessing/deskew_crop.hh: New.
* preprocessing/unskew.hh: Remove. Deprecated.
* tests/preprocessing/unskew.cc: Rename as...
* tests/preprocessing/deskew.cc: ... this.
* tests/preprocessing/Makefile.am: Update.
* tests/img/text_to_group.pgm: New test image.
---
scribo/ChangeLog | 16 +
scribo/preprocessing/deskew.hh | 437 ++++++++++++++++++++
scribo/preprocessing/deskew_crop.hh | 187 +++++++++
scribo/preprocessing/unskew.hh | 115 -----
scribo/tests/img/text_to_group.pgm | Bin 0 -> 3053 bytes
scribo/tests/preprocessing/Makefile.am | 4 +-
.../tests/preprocessing/{unskew.cc => deskew.cc} | 22 +-
7 files changed, 657 insertions(+), 124 deletions(-)
create mode 100644 scribo/preprocessing/deskew.hh
create mode 100644 scribo/preprocessing/deskew_crop.hh
delete mode 100644 scribo/preprocessing/unskew.hh
create mode 100644 scribo/tests/img/text_to_group.pgm
rename scribo/tests/preprocessing/{unskew.cc => deskew.cc} (74%)
diff --git a/scribo/ChangeLog b/scribo/ChangeLog
index c5476be..623147b 100644
--- a/scribo/ChangeLog
+++ b/scribo/ChangeLog
@@ -1,5 +1,21 @@
2010-05-25 Guillaume Lazzara <z(a)lrde.epita.fr>
+ Add a new deskew algorithm.
+
+ * preprocessing/deskew.hh,
+ * preprocessing/deskew_crop.hh: New.
+
+ * preprocessing/unskew.hh: Remove. Deprecated.
+
+ * tests/preprocessing/unskew.cc: Rename as...
+ * tests/preprocessing/deskew.cc: ... this.
+
+ * tests/preprocessing/Makefile.am: Update.
+
+ * tests/img/text_to_group.pgm: New test image.
+
+2010-05-25 Guillaume Lazzara <z(a)lrde.epita.fr>
+
Add crop tools.
* preprocessing/crop.hh,
diff --git a/scribo/preprocessing/deskew.hh b/scribo/preprocessing/deskew.hh
new file mode 100644
index 0000000..27d38a1
--- /dev/null
+++ b/scribo/preprocessing/deskew.hh
@@ -0,0 +1,437 @@
+// Copyright (C) 2010 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_PREPROCESSING_DESKEW_HH
+# define SCRIBO_PREPROCESSING_DESKEW_HH
+
+/// \file
+///
+/// Deskew an image.
+
+/// \FIXME: provide a version for binary images.
+
+
+# include <queue>
+# include <mln/core/image/image2d.hh>
+# include <mln/math/pi.hh>
+# include <mln/geom/rotate.hh>
+
+# define PI 3.1415926535897932384
+
+namespace scribo
+{
+
+ namespace preprocessing
+ {
+
+ using namespace mln;
+
+ namespace internal
+ {
+
+ class Hough
+ {
+ public:
+ Hough(int width, int height);
+
+ ~Hough();
+
+ void look_up_table();
+
+ int width() const;
+
+ int height() const;
+
+ double mtheta() const;
+ double mrho() const;
+
+ int mrhoi() const;
+ int mthetai() const;
+
+ double get_cos(int index) const;
+ double get_sin(int index) const;
+
+ image2d<unsigned>& acc();
+
+ private:
+ int width_;
+ int height_;
+
+ double max_rho_;
+ double max_theta_;
+
+ int max_rho_index_;
+ int max_theta_index_;
+
+ double* cos_;
+ double* sin_;
+
+ image2d<unsigned> acc_;
+ };
+
+
+ struct s_angle
+ {
+ int pos;
+ unsigned max;
+ };
+
+
+ struct QCompare
+ {
+ bool operator()(const s_angle& s1, const s_angle& s2);
+ };
+
+ } // end of namespace scribo::preprocessing::internal
+
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ namespace internal
+ {
+
+ bool
+ QCompare::operator()(const s_angle& s1, const s_angle& s2)
+ {
+ return (s1.max > s2.max);
+ }
+
+
+ Hough::Hough(int width, int height)
+ : width_(width / 2),
+ height_(height / 2),
+ max_rho_(sqrt((width * width) + (height * height))),
+ max_theta_(math::pi),
+ max_rho_index_(this->max_rho_ + 1),
+ max_theta_index_(500),
+ acc_(this->max_rho_index_, this->max_theta_index_)
+ {
+ look_up_table();
+ }
+
+
+ Hough::~Hough()
+ {
+ delete[] this->cos_;
+ delete[] this->sin_;
+ }
+
+ inline
+ void Hough::look_up_table()
+ {
+ this->cos_ = new double[this->max_theta_index_];
+ this->sin_ = new double[this->max_theta_index_];
+
+ for (int i = 0; i < this->max_theta_index_; ++i)
+ {
+ double i_val = (i + 650) * this->max_theta_ / 1800.0f;
+
+ this->cos_[i] = cos(i_val);
+ this->sin_[i] = sin(i_val);
+ }
+ }
+
+ inline
+ int Hough::width() const
+ {
+ return this->width_;
+ }
+
+ inline
+ int Hough::height() const
+ {
+ return this->height_;
+ }
+
+ inline
+ double Hough::mtheta() const
+ {
+ return this->max_theta_;
+ }
+
+ inline
+ double Hough::mrho() const
+ {
+ return this->max_rho_;
+ }
+
+ inline
+ int Hough::mrhoi() const
+ {
+ return this->max_rho_index_;
+ }
+
+ inline
+ int Hough::mthetai() const
+ {
+ return this->max_theta_index_;
+ }
+
+ inline
+ double Hough::get_cos(int index) const
+ {
+ return this->cos_[index];
+ }
+
+ inline
+ double Hough::get_sin(int index) const
+ {
+ return this->sin_[index];
+ }
+
+ inline
+ image2d<unsigned>& Hough::acc()
+ {
+ return this->acc_;
+ }
+
+ inline
+ static
+ void
+ vote(int x, int y, Hough& hough, int theta)
+ {
+ int theta_min = std::max(theta - 25, 0);
+ int theta_max = std::min(theta + 25, hough.mthetai());
+
+ x -= hough.width();
+ y -= hough.height();
+
+ for (int i = theta_min; i < theta_max; ++i)
+ {
+ double rho = x * hough.get_cos(i) + y * hough.get_sin(i);
+ double rho_index = (0.5 + (rho / hough.mrho() + 0.5)
+ * hough.mrhoi());
+
+ ++(opt::at(hough.acc(), rho_index, i));
+ }
+ }
+
+
+ inline
+ static
+ void
+ init_hist(Hough& hough, int hist[500],
+ std::priority_queue<s_angle, std::vector<s_angle>, QCompare>& q,
+ int nb_elm)
+ {
+ int max_rho = hough.mrhoi();
+ int max_theta = hough.mthetai();
+ unsigned max_elm = (nb_elm > max_rho) ? (nb_elm / max_rho) << 5 : 1;
+
+ for (int j = 0; j < max_theta; ++j)
+ {
+ hist[j] = 0;
+
+ if (q.size() < max_elm)
+ {
+ if (opt::at(hough.acc(), 0, j) > 0)
+ {
+ s_angle s;
+
+ s.max = opt::at(hough.acc(), 0, j);
+ s.pos = j;
+
+ q.push(s);
+ }
+ }
+ else if (opt::at(hough.acc(), 0, j) > q.top().max)
+ {
+ s_angle s;
+
+ s.max = opt::at(hough.acc(), 0, j);
+ s.pos = j;
+
+ q.pop();
+ q.push(s);
+ }
+ }
+ }
+
+
+ inline
+ static
+ double
+ get_max(Hough& hough, int hist[500],
+ std::priority_queue<s_angle, std::vector<s_angle>, QCompare>& q,
+ int nb_elm)
+ {
+ int max = 0;
+ int h_value = 0;
+ int max_rho = hough.mrhoi();
+ int max_theta = hough.mthetai();
+ double pos = 0.f;
+ unsigned max_elm = (nb_elm > max_rho) ? (nb_elm / max_rho) << 5 : 1;
+
+
+ for (int i = 1; i < max_rho; ++i)
+ {
+ for (int j = 0; j < max_theta; ++j)
+ {
+ if (q.size() < max_elm)
+ {
+ if (opt::at(hough.acc(), i, j) > 0)
+ {
+ s_angle s;
+
+ s.max = opt::at(hough.acc(), i, j);
+ s.pos = j;
+
+ q.push(s);
+ }
+ }
+ else if (opt::at(hough.acc(), i, j) > q.top().max)
+ {
+ s_angle s;
+
+ s.max = opt::at(hough.acc(), i, j);
+ s.pos = j;
+
+ q.pop();
+ q.push(s);
+ }
+ }
+ }
+
+ while (!q.empty())
+ {
+ hist[q.top().pos] += q.top().max;
+ h_value = hist[q.top().pos];
+
+ if (h_value > max)
+ {
+ max = h_value;
+ pos = q.top().pos;
+ }
+
+ q.pop();
+ }
+
+ return pos;
+ }
+
+
+ double
+ perform_deskew(const image2d<value::int_u8>& gray)
+ {
+ Hough hough(gray.ncols(), gray.nrows());
+ std::priority_queue<s_angle, std::vector<s_angle>, QCompare> q;
+ int hist[500];
+ int nb_elm = 0;
+
+ for (unsigned i = 0; i < gray.nrows() - 1; ++i)
+ {
+ for (unsigned j = 1; j < gray.ncols() - 1; ++j)
+ {
+ unsigned up = 1;
+ unsigned down = 1;
+ unsigned mean = ((opt::at(gray, i, j) * opt::at(gray, i + 1, j))) >> 8;
+
+ for (unsigned k = j - 1; k <= j + 1; ++k)
+ {
+ up *= opt::at(gray, i, k);
+ down *= opt::at(gray, i + 1, k);
+ }
+
+ up = 255 - (up >> 16);
+ down = down >> 16;
+
+ if (up > down && down > mean && down > 130)
+ {
+
+ ++nb_elm;
+ double gy = opt::at(gray, i - 1, j - 1) + 2 * opt::at(gray, i - 1, j) +
+ opt::at(gray, i - 1, j + 1);
+ gy += -opt::at(gray, i + 1, j - 1) - 2 * opt::at(gray, i + 1, j) -
+ opt::at(gray, i + 1, j + 1);
+
+ double gx = opt::at(gray, i - 1, j - 1) + 2 * opt::at(gray, i, j - 1) +
+ opt::at(gray, i + 1, j - 1);
+ gx += -opt::at(gray, i - 1, j + 1) - 2 * opt::at(gray, i, j + 1) -
+ opt::at(gray, i + 1, j + 1);
+
+ double tanv = (PI / 2.0 - atan(gy / gx)) * 180.0 / PI;
+
+ if (tanv <= 25.0 || tanv >= 155.0)
+ {
+ ++nb_elm;
+ vote(j, i, hough, (tanv <= 25.0 ? 250.0 - tanv * 10.0 :
+ (180.0 - tanv) * 10.0 + 250.0));
+ }
+ }
+ }
+ }
+
+ init_hist(hough, hist, q, nb_elm);
+
+ return 90 - (get_max(hough, hist, q, nb_elm) + 650) / 10;
+ }
+
+
+
+ } // end of namespace scribo::preprocessing::internal
+
+
+
+ template <typename I>
+ mln_concrete(I)
+ deskew(const Image<I>& input_gl_)
+ {
+ const I& input_gl = exact(input_gl_);
+
+ trace::entering("scribo::preprocessing::deskew");
+ mln_assertion(input_gl.is_valid());
+ mlc_is(mln_domain(I), box2d)::check();
+ mlc_is_not(mln_value(I), bool)::check();
+ mlc_is_not_a(mln_value(I), value::Vectorial)::check();
+
+ double angle = internal::perform_deskew(input_gl);
+// std::cout << angle << std::endl;
+
+ mln_concrete(I) output = input_gl;
+
+ // FIXME: trick to make this routine faster for really small
+ // angles (no impact on the results)
+ if (angle > 0.5 || angle < -0.5)
+ output = geom::rotate(input_gl, - angle,
+ //mln_max(mln_value(I)),
+ extend(input_gl, mln_max(mln_value(I))),
+ make::box2d(input_gl.nrows(),
+ input_gl.ncols()));
+
+ trace::exiting("scribo::preprocessing::deskew");
+ return output;
+ }
+
+
+# endif // ! MLN_INCLUDE_ONLY
+
+
+ } // end of namespace scribo::preprocessing
+
+} // end of namespace scribo
+
+
+# endif // SCRIBO_PREPROCESSING_DESKEW_HH
diff --git a/scribo/preprocessing/deskew_crop.hh b/scribo/preprocessing/deskew_crop.hh
new file mode 100644
index 0000000..3b15cb1
--- /dev/null
+++ b/scribo/preprocessing/deskew_crop.hh
@@ -0,0 +1,187 @@
+// Copyright (C) 2010 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_PREPROCESSING_DESKEW_CROP_HH
+# define SCRIBO_PREPROCESSING_DESKEW_CROP_HH
+
+/// \file
+///
+/// \brief Deskew a region of interest.
+
+# include <scribo/preprocessing/deskew.hh>
+
+namespace scribo
+{
+
+ namespace preprocessing
+ {
+
+ /*! \brief Deskew a region of interest.
+
+ \param[in] input_bin A binary image.
+ \param[in] input_gray A gray-level image.
+
+ \return A deskewed binary image.
+
+
+
+ Handles skew angles from -25 to +25 degrees.
+
+ \p input_bin and \p input_gray must be 2D images and must be
+ identical (e.g. only the value differs).
+
+ This algorithm is designed for images created from a region of
+ interest (e.g. Not a full document).
+
+ */
+ template <typename I, typename J>
+ mln_concrete(I)
+ deskew(const Image<I>& crop_gl_, const Image<I>& input_gl_);
+
+# ifndef MLN_INCLUDE_ONLY
+
+ namespace internal
+ {
+
+
+ /*! \brief Compute the skew angle using a Hough transform.
+
+ \param[in] input_bin A binary image.
+ \param[in] input_gray A gray-level image.
+ \param[in] threshold
+ \param[in] length
+
+ \return A deskewed binary image.
+
+ This algorithm tries to use only the sites located on the
+ baselines (the most relevant sites for deskewing).
+ A site is considered as relevant for this algorithm if :
+ - \p threshold sites in the window of length \p length are set to True.
+ - The bottom left, bottom and bottom right sites are set to False.
+
+ Note: Increasing \p length value while keeping threshold value
+ low increases the number of relevant sites.
+
+ Handles skew angles from -25 to +25 degrees.
+
+ \p input_bin and \p input_gray must be 2D images and must be
+ identical (e.g. only the value differs).
+
+ This algorithm is designed for images created from a region of
+ interest (e.g. Not a full document).
+
+ */
+// double
+// perform_deskew_crop(const image2d<bool>& input_bin,
+// const image2d<value::int_u8>& input_gray,
+// int threshold,
+// int length)
+// {
+// Hough hough(input_bin.ncols(), input_bin.nrows());
+// int
+// mid = length >> 1,
+// max = 0;
+// double pos = 0;
+
+// for (int i = 1; i < input_bin.nrows() - 1; ++i)
+// {
+// int
+// acc = 0,
+// begin = 0,
+// end = length;
+
+// for (int j = 0; j < length; ++j)
+// acc += opt::at(input_bin, i, j);
+
+// for (int j = mid + 1; end < input_bin.ncols(); ++j, ++end, ++begin)
+// {
+// acc += opt::at(input_bin, i, end) - opt::at(input_bin, i, begin);
+
+// if (acc > threshold && !opt::at(input_bin, i + 1, j) &&
+// !opt::at(input_bin, i + 1, j - 1) && !opt::at(input_bin, i + 1, j + 1))
+// {
+// double gy = opt::at(input_gray, i - 1, j - 1) + 2 * opt::at(input_gray, i - 1, j) + opt::at(input_gray, i - 1, j + 1);
+// gy += - opt::at(input_gray, i + 1, j - 1) - 2 * opt::at(input_gray, i + 1, j) - opt::at(input_gray, i + 1, j + 1);
+
+// double gx = opt::at(input_gray, i - 1, j - 1) + 2 * opt::at(input_gray, i, j - 1) + opt::at(input_gray, i + 1, j - 1);
+// gx += - opt::at(input_gray, i - 1, j + 1) - 2 * opt::at(input_gray, i, j + 1) - opt::at(input_gray, i + 1, j + 1);
+
+// if (abs(gx) + abs(gy) >= 255)
+// vote(j, i, deskew, &max, &pos);
+// }
+// }
+// }
+
+// return 90 - (pos + 650) / 10.0f;
+// }
+
+
+// } // end of namespace scribo::preprocessing::internal
+
+
+ // Facade
+
+
+ template <typename I>
+ mln_concrete(I)
+ deskew(const Image<I>& crop_gl_, const Image<I>& input_gl_)
+ {
+ const I& crop_gl = exact(crop_gl_);
+ const I& input_gl = exact(input_gl_);
+
+ trace::entering("scribo::preprocessing::deskew_crop");
+ mln_assertion(crop_gl.is_valid());
+ mln_assertion(input_gl.is_valid());
+ mlc_is(mln_domain(I), box2d)::check();
+ mlc_is_not(mln_value(I), bool)::check();
+ mlc_is_not_a(mln_value(I), value::Vectorial)::check();
+
+ double angle = internal::perform_deskew(crop_gl);
+ std::cout << angle << std::endl;
+
+ mln_concrete(I) output = crop_gl;
+
+ // FIXME: trick to make this routine faster for really small
+ // angles (no impact on the results)
+ if (angle > 0.5 || angle < -0.5)
+ output = geom::rotate(crop_gl, - angle,
+ //mln_max(mln_value(I)),
+ extend(input_gl, mln_max(mln_value(I))),
+ make::box2d(crop_gl.nrows(),
+ crop_gl.ncols()));
+
+ trace::exiting("scribo::preprocessing::deskew_crop");
+ return output;
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+
+ } // end of namespace scribo::preprocessing
+
+} // end of namespace scribo
+
+
+# endif // SCRIBO_PREPROCESSING_DESKEW_CROP_HH
diff --git a/scribo/preprocessing/unskew.hh b/scribo/preprocessing/unskew.hh
deleted file mode 100644
index a01cae3..0000000
--- a/scribo/preprocessing/unskew.hh
+++ /dev/null
@@ -1,115 +0,0 @@
-// 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_PREPROCESSING_UNSKEW_HH
-# define SCRIBO_PREPROCESSING_UNSKEW_HH
-
-/// \file
-///
-/// Unskew an image.
-
-# include <mln/core/image/image2d.hh>
-
-# include <mln/accu/compute.hh>
-# include <mln/accu/max_site.hh>
-
-# include <mln/transform/hough.hh>
-# include <mln/geom/rotate.hh>
-
-# include <mln/io/pgm/save.hh>
-# include <mln/core/image/vmorph/cast_image.hh>
-# include <mln/value/int_u8.hh>
-
-# include <mln/util/couple.hh>
-
-namespace scribo
-{
-
- namespace preprocessing
- {
-
- using namespace mln;
-
- /// Unskew a document.
- /// Based on the Hough transform.
- ///
- /// \param[in] input_ A binary image. Objects to be unskewed must be set
- /// to "true".
- ///
- /// \return A binary image.
- //
- template <typename I>
- mln::util::couple<mln_concrete(I), double>
- unskew(const Image<I>& input_);
-
-
-
-# ifndef MLN_INCLUDE_ONLY
-
-
- template <typename I>
- mln::util::couple<mln_concrete(I), double>
- unskew(const Image<I>& input_)
- {
- trace::entering("scribo::preprocessing::unskew");
-
- const I& input = exact(input_);
- mlc_equal(mln_value(I), bool)::check();
- mln_precondition(input.is_valid());
-
- image2d<float> hough_ima = transform::hough(input);
-
- point2d max_p = accu::compute(accu::max_site<image2d<float> >(), hough_ima);
-
- double angle = 0;
- int max_angle = max_p.row();
-
-// std::cout << "max_angle = " << max_angle << std::endl;
- if (max_angle > 180)
- max_angle = - max_angle % 180;
-
- if (max_angle < 90 && max_angle > 0)
- angle = - max_angle;
- else if (max_angle < 0 && max_angle > -90)
- angle = max_angle;
- else if (max_angle < 180 && max_angle > 90)
- angle = 180 - max_angle;
- else if (max_angle < -90 && max_angle > -180)
- angle = 180 + max_angle;
-
-// std::cout << "effective angle = " << angle << std::endl;
- mln_concrete(I) output = geom::rotate(input, angle);
-
- trace::exiting("scribo::preprocessing::unskew");
- return mln::make::couple(output, angle);
- }
-
-# endif // ! MLN_INCLUDE_ONLY
-
- } // end of namespace scribo::preprocessing
-
-} // end of namespace mln
-
-# endif // SCRIBO_PREPROCESSING_UNSKEW_HH
diff --git a/scribo/tests/img/text_to_group.pgm b/scribo/tests/img/text_to_group.pgm
new file mode 100644
index 0000000000000000000000000000000000000000..220ffbaa2e49e0b1e8fe644de06e4d627748d19e
GIT binary patch
literal 3053
zcmWGA<x*B~4svx2@ei_6aQE~LPzdnzRdCD9DM>9-2um$0&dkqKFw`^T;xaQ(Fg4&Z
zGBxF57zLvtFd70wHw6B}0Rx=%pD+{b;r}pi12vGq9MuaAEFyw!V8aTYA_yl4xKemZ
zfTf60nwBAeJ=}>Cg+~>f0dgsv17~0pg-gO2*i?bUFinJOfitkF0&B%^4O|PHF{&35
YQdq(no(y0rz+pv#D6+m$_Am+o0N4yHPXGV_
literal 0
HcmV?d00001
diff --git a/scribo/tests/preprocessing/Makefile.am b/scribo/tests/preprocessing/Makefile.am
index d180604..f94a852 100644
--- a/scribo/tests/preprocessing/Makefile.am
+++ b/scribo/tests/preprocessing/Makefile.am
@@ -23,11 +23,11 @@ check_PROGRAMS = \
crop \
crop_without_localization \
rotate_90 \
- unskew
+ deskew
crop_SOURCES = crop.cc
crop_without_localization_SOURCES = crop_without_localization.cc
rotate_90_SOURCES = rotate_90.cc
-unskew_SOURCES = unskew.cc
+deskew_SOURCES = deskew.cc
TESTS = $(check_PROGRAMS)
diff --git a/scribo/tests/preprocessing/unskew.cc b/scribo/tests/preprocessing/deskew.cc
similarity index 74%
rename from scribo/tests/preprocessing/unskew.cc
rename to scribo/tests/preprocessing/deskew.cc
index 9c84951..5b55889 100644
--- a/scribo/tests/preprocessing/unskew.cc
+++ b/scribo/tests/preprocessing/deskew.cc
@@ -1,4 +1,5 @@
-// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE)
+// Copyright (C) 2009, 2010 EPITA Research and Development Laboratory
+// (LRDE)
//
// This file is part of Olena.
//
@@ -23,11 +24,16 @@
// exception does not however invalidate any other reasons why the
// executable file might be covered by the GNU General Public License.
+/// \file
+///
+/// \fixme Add a better test.....
+
#include <mln/core/image/image2d.hh>
-#include <mln/io/pbm/load.hh>
-#include <mln/io/pbm/save.hh>
+#include <mln/io/pgm/all.hh>
+#include <mln/value/int_u8.hh>
+#include <mln/data/compare.hh>
-#include <scribo/preprocessing/unskew.hh>
+#include <scribo/preprocessing/deskew.hh>
#include <scribo/tests/data.hh>
@@ -37,8 +43,10 @@ int main(int argc, char *argv[])
(void) argv;
using namespace mln;
- image2d<bool> ima;
- io::pbm::load(ima, SCRIBO_IMG_DIR "/text_to_group.pbm");
+ image2d<value::int_u8> ima;
+ io::pgm::load(ima, SCRIBO_IMG_DIR "/text_to_group.pgm");
+
+ image2d<value::int_u8> tmp = scribo::preprocessing::deskew(ima);
- io::pbm::save(scribo::preprocessing::unskew(ima).first(), "unskew.pbm");
+ mln_assertion(ima == tmp);
}
--
1.5.6.5