
https://svn.lrde.epita.fr/svn/oln/trunk/milena/sandbox Index: ChangeLog from Thierry Geraud <thierry.geraud@lrde.epita.fr> Augment ICDAR-HSC. * icdar/2009/hsc/line_to_words.hh: New. * icdar/2009/hsc/input_to_wsl.cc: Add some log. * icdar/2009/hsc/line_to_words.cc: New. * icdar/2009/hsc/ws_to_wsl.hh (pass): New. (ws_to_wslines): Use the 'pass' routine. * theo/icdar/hsc/reduce.sh: New. * theo/icdar/hsc/words.sh: New. icdar/2009/hsc/input_to_wsl.cc | 5 + icdar/2009/hsc/line_to_words.cc | 45 +++++++++++++++ icdar/2009/hsc/line_to_words.hh | 114 ++++++++++++++++++++++++++++++++++++++++ icdar/2009/hsc/ws_to_wsl.hh | 48 ++++++++++++++-- theo/icdar/hsc/reduce.sh | 4 + theo/icdar/hsc/words.sh | 7 ++ 6 files changed, 215 insertions(+), 8 deletions(-) Index: icdar/2009/hsc/line_to_words.hh --- icdar/2009/hsc/line_to_words.hh (revision 0) +++ icdar/2009/hsc/line_to_words.hh (revision 0) @@ -0,0 +1,114 @@ + +#include <mln/value/int_u.hh> + +#include <mln/core/image/image2d.hh> +#include <mln/core/alias/neighb2d.hh> + +#include <mln/transform/distance_front.hh> +#include <mln/make/w_window2d_int.hh> +#include <mln/win/rectangle2d.hh> + +#include <mln/morpho/closing/structural.hh> +#include <mln/morpho/closing/area.hh> +#include <mln/morpho/elementary/dilation.hh> +#include <mln/morpho/watershed/flooding.hh> + + + +namespace mln +{ + + + image2d<bool> // Fwd decl. + reduce_negate(const image2d<bool>& input); + + + + template <typename L> + image2d<L> + line_to_words(const image2d<bool>& input, L& n_words) + { + // Parameters. + + const unsigned + height = 5, + width = 11, + l_area = 500; + + // end of Parameters. + + + image2d<bool> + sub = reduce_negate(input), + clo = morpho::closing::structural(sub, + win::rectangle2d(height, + width)); + + int ww[] = { 00, 11, 0, 11, 0, + 11, 7, 5, 7, 11, + 00, 5, 0, 5, 0, + 11, 7, 5, 7, 11, + 00, 11, 0, 11, 0 }; + + typedef value::int_u<12> int_u12; + image2d<int_u12> + dmap = transform::distance_front(clo, + c4(), make::w_window2d_int(ww), + mln_max(int_u12)), + dmap_ = morpho::closing::area(dmap, c4(), l_area); + + image2d<L> ws = morpho::elementary::dilation(morpho::watershed::flooding(dmap_, + c4(), + n_words), + c4()); + + image2d<L> output(input.domain()); + + { + const int + min_row = input.domain().pmin().row(), + min_col = input.domain().pmin().col(); + + mln_piter_(box2d) p(input.domain()); + for_all(p) + if (input(p)) + output(p) = 0; + else + output(p) = ws.at_((p.row() - min_row) / 2, + (p.col() - min_col) / 2); + } + + return output; + } + + + + image2d<bool> + reduce_negate(const image2d<bool>& input) + { + const int + min_row = input.domain().pmin().row(), + min_col = input.domain().pmin().col(), + max_row = input.domain().pmax().row(), + max_col = input.domain().pmax().col(); + + image2d<bool> output(input.nrows() / 2, + input.ncols() / 2); + + for (int row = min_row; row <= max_row; row += 2) + for (int col = min_col; col <= max_col; col += 2) + { + unsigned count = 0; + if (input.at_(row, col) == false) ++count; + if (input.at_(row, col + 1) == false) ++count; + if (input.at_(row + 1, col) == false) ++count; + if (input.at_(row + 1, col + 1) == false) ++count; + output.at_((row - min_row) / 2, + (col - min_col) / 2) = (count >= 2); + } + return output; + } + + + +} // ! mln Index: icdar/2009/hsc/input_to_wsl.cc --- icdar/2009/hsc/input_to_wsl.cc (revision 3629) +++ icdar/2009/hsc/input_to_wsl.cc (working copy) @@ -115,6 +115,11 @@ int_u8 n_basins; ws = morpho::watershed::flooding(clo, c4(), n_basins); +# ifdef LOG + io::pgm::save(ws, "tmp_ws.pgm"); + io::ppm::save(debug::colorize(rgb8(), ws, n_basins), "tmp_ws.ppm"); +# endif + image2d<int_u8> wsl = ws_to_wslines(input, small, ws, n_basins); Index: icdar/2009/hsc/line_to_words.cc --- icdar/2009/hsc/line_to_words.cc (revision 0) +++ icdar/2009/hsc/line_to_words.cc (revision 0) @@ -0,0 +1,45 @@ +#include <mln/value/int_u8.hh> + +#include <mln/io/pbm/load.hh> +#include <mln/io/pgm/save.hh> + +#include <sandbox/icdar/2009/hsc/line_to_words.hh> + + + + +void usage(char* argv[]) +{ + std::cerr << "usage: " << argv[0] << " line.pbm output.pgm" << std::endl + << " HSC @ ICDAR'2009" << std::endl + << " line.pbm: a 2D image of a line (text is black; background is white)" << std::endl + << " output.pgm: output image where words are labeled (int_u8)" << std::endl + << " 0 is the background label." << std::endl; + std::abort(); +} + + + +int main(int argc, char* argv[]) +{ + using namespace mln; + using value::int_u8; + + if (argc != 3) + usage(argv); + + + trace::entering("main"); + + + image2d<bool> input; + io::pbm::load(input, argv[1]); + + int_u8 n_words; + image2d<int_u8> output = line_to_words(input, n_words); + + io::pgm::save(output, argv[2]); + + + trace::exiting("main"); +} Index: icdar/2009/hsc/ws_to_wsl.hh --- icdar/2009/hsc/ws_to_wsl.hh (revision 3629) +++ icdar/2009/hsc/ws_to_wsl.hh (working copy) @@ -1,3 +1,5 @@ +#include <cmath> + #include <mln/core/var.hh> #include <mln/core/image/image2d.hh> @@ -101,13 +103,17 @@ if (n_ == 0) return; mean_ /= n_; - algebra::mat<2,1,float> mu; cov_ = cov_ / n_ - to_mat(mean_) * trans(mean_); float a = cov_(0, 0), b = cov_(0, 1), c = cov_(1, 0), d = cov_(1, 1), r = a * d - b * c; + + float D = std::sqrt((a - d) * (a - d) + 4 * b * c); + lambda1_ = 0.5 * (a + d + D); + lambda2_ = 0.5 * (a + d - D); + if (r > -0.001f && r < 0.001f) // too close to 0 { n_ = 0; // invalidation @@ -174,12 +180,16 @@ return valid_; } + float lambda1() const { return lambda1_; } + float lambda2() const { return lambda2_; } + protected: bool valid_; unsigned n_; algebra::vec<2,float> mean_; algebra::mat<2,2,float> cov_, cov_1_; + float lambda1_, lambda2_; }; @@ -225,6 +235,31 @@ + bool + pass(const util::array<mahalanobis>& m, + unsigned l, unsigned r) + { + float + // vertical std deviations + vs_l = std::sqrt(m[l].cov()(0, 0)), + vs_r = std::sqrt(m[r].cov()(0, 0)), + // vertical distance + vd = std::abs(m[l].mean()[0] - m[r].mean()[0]), + // horizontal std deviations + hs_l = std::sqrt(m[l].cov()(1, 1)), + hs_r = std::sqrt(m[r].cov()(1, 1)), + // horizontal means (column coordinates) + hm_l = m[l].mean()[1], + hm_r = m[r].mean()[1]; + + bool + v_criterion = (vd < 5 * std::sqrt(vs_l * vs_r)), // FIXME: say 4? + h_criterion = (hm_r - 1 * hs_r > hm_l + 1 * hs_l); // FIXME: say 1.5? + + return v_criterion && h_criterion; + } + + template <typename L> image2d<L> @@ -296,7 +331,8 @@ if (m[v2].col() < v_col) { // v2 <-- v - if (d_ < d_left_min) + if (pass(m, v2, v.id()) + && d_ < d_left_min) { d_left_min = d_; v_left_best = v2; @@ -305,7 +341,8 @@ else { // v --> v2 - if (d_ < d_right_min) + if (pass(m, v.id(), v2) + && d_ < d_right_min) { d_right_min = d_; v_right_best = v2; @@ -319,7 +356,6 @@ } - util::array<L> parent(n_basins + 1); // Computing parent. @@ -334,11 +370,7 @@ continue; unsigned r = v_right[l]; if (v_left[r] != l) - { - // std::cout << '.' << std::endl; continue; - } - // std::cout << l << " -> " << r << std::endl; parent[l] = r; } Index: theo/icdar/hsc/reduce.sh --- theo/icdar/hsc/reduce.sh (revision 0) +++ theo/icdar/hsc/reduce.sh (revision 0) @@ -0,0 +1,4 @@ +#! /bin/sh + +convert -negate -geometry 50% +compress -depth 8 $1 ${1%.pbm}_50p.pbm +convert -depth 8 +compress ${1%.pbm}_50p.pbm ${1%.pbm}_50p.pgm Property changes on: theo/icdar/hsc/reduce.sh ___________________________________________________________________ Added: svn:executable + * Index: theo/icdar/hsc/words.sh --- theo/icdar/hsc/words.sh (revision 0) +++ theo/icdar/hsc/words.sh (revision 0) @@ -0,0 +1,7 @@ +#! /bin/sh + +./+bin/closing_rectangle $1 5 11 tmp_small_clo.pbm +./+bin/distance_thick tmp_small_clo.pbm tmp_dist.pgm +./+bin/closing_area tmp_dist.pgm 500 tmp_clo.pgm +./+bin/watershed_flooding tmp_clo.pgm tmp_ws.pgm +./+bin/watershed_superpose ${1%pbm}pgm tmp_ws.pgm ${1%pbm}ppm Property changes on: theo/icdar/hsc/words.sh ___________________________________________________________________ Added: svn:executable + *
participants (1)
-
Thierry Geraud