3628: Add new small tools for ICDAR.

* icdar/2009/hsc/input_lines_to_lines.cc: Iterate on lbl.domain(). * icdar/2009/hsc/label_maj.hh: new accumulator computing the most represented label in a component. * icdar/2009/hsc/lines_to_words.cc: basic canvas for splitting lines into words. --- milena/sandbox/ChangeLog | 12 ++ .../sandbox/icdar/2009/hsc/input_lines_to_lines.cc | 12 +- milena/sandbox/icdar/2009/hsc/label_maj.hh | 197 ++++++++++++++++++++ milena/sandbox/icdar/2009/hsc/lines_to_words.cc | 98 ++++++++++ 4 files changed, 314 insertions(+), 5 deletions(-) create mode 100644 milena/sandbox/icdar/2009/hsc/label_maj.hh create mode 100644 milena/sandbox/icdar/2009/hsc/lines_to_words.cc diff --git a/milena/sandbox/ChangeLog b/milena/sandbox/ChangeLog index ba700f8..37485b0 100644 --- a/milena/sandbox/ChangeLog +++ b/milena/sandbox/ChangeLog @@ -1,5 +1,17 @@ 2009-04-07 Guillaume Lazzara <z@lrde.epita.fr> + Add new small tools for ICDAR. + + * icdar/2009/hsc/input_lines_to_lines.cc: Iterate on lbl.domain(). + + * icdar/2009/hsc/label_maj.hh: new accumulator computing the most + represented label in a component. + + * icdar/2009/hsc/lines_to_words.cc: basic canvas for splitting lines + into words. + +2009-04-07 Guillaume Lazzara <z@lrde.epita.fr> + Add new known bugs in sandbox. * bugs/algebra_vec_ne_op.cc: issues with algebra::vec operators. diff --git a/milena/sandbox/icdar/2009/hsc/input_lines_to_lines.cc b/milena/sandbox/icdar/2009/hsc/input_lines_to_lines.cc index eb46b36..56aafab 100644 --- a/milena/sandbox/icdar/2009/hsc/input_lines_to_lines.cc +++ b/milena/sandbox/icdar/2009/hsc/input_lines_to_lines.cc @@ -6,17 +6,17 @@ #include <mln/value/label_16.hh> #include <mln/io/pbm/load.hh> #include <mln/io/pgm/all.hh> -#include <mln/accu/lbl_maj.hh> #include <mln/labeling/compute.hh> #include <mln/pw/all.hh> #include <mln/core/image/image_if.hh> #include <mln/data/fill.hh> +#include "label_maj.hh" void usage(char* argv[]) { std::cerr << "usage: " << argv[0] << " input.pbm lines.pgm output.pgm" << std::endl << " HSC @ ICDAR'2009" << std::endl - << " Rebuild splitted components from a label image." << std::endl; + << " Rebuild splitted components from a label image." << std::endl << " input.pbm: input 2D binary image (text is black; background is white)" << std::endl << " lines.pgm: output image where line components are labeled (int_u8)" << std::endl << " 0 is the background label." << std::endl @@ -45,8 +45,8 @@ int main(int argc, char *argv[]) util::array<box2d> bboxes = labeling::compute(accu::meta::bbox(), lbl, nlabels); /// Compute the most represented label for each component. - accu::lbl_maj<label_16, int_u8> accu(nlabels.next()); - mln_piter_(image2d<int_u8>) p(lines.domain()); + accu::label_maj<label_16, int_u8> accu(nlabels.next()); + mln_piter_(image2d<int_u8>) p(lbl.domain()); for_all(p) if (lines(p) != 0u) accu.take(lbl(p), lines(p)); @@ -55,8 +55,10 @@ int main(int argc, char *argv[]) // Rebuild components. util::array<util::couple<int_u8, float> > res = accu.to_result(); for (unsigned i = 1; i < res.nelements(); ++i) - if (res[i].second() >= 0.9f) + if (res[i].second() >= 0.70f) data::fill(((lines | bboxes[i]).rw() | (pw::value(lbl) != 0u)).rw(), res[i].first()); + else + std::cout << res[i].first() << " - " << res[i].second() << std::endl; // Save result. io::pgm::save(lines, argv[3]); diff --git a/milena/sandbox/icdar/2009/hsc/label_maj.hh b/milena/sandbox/icdar/2009/hsc/label_maj.hh new file mode 100644 index 0000000..a46241c --- /dev/null +++ b/milena/sandbox/icdar/2009/hsc/label_maj.hh @@ -0,0 +1,197 @@ +// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE) +// +// This file is part of the Olena Library. This library is free +// software; you can redistribute it and/or modify it under the terms +// of the GNU General Public License version 2 as published by the +// Free Software Foundation. +// +// This library 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 this library; see the file COPYING. If not, write to +// the Free Software Foundation, 51 Franklin Street, Fifth Floor, +// Boston, MA 02111-1307, USA. +// +// As a special exception, you may use this file as part of a free +// software library 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 MLN_ACCU_LABEL_MAJ_HH +# define MLN_ACCU_LABEL_MAJ_HH + +/// \file mln/accu/label_maj.hh +/// +/// Define an accumulator that computes the most represented label in +/// a component. + + +# include <mln/core/concept/meta_accumulator.hh> +# include <mln/accu/internal/base.hh> +# include <mln/trait/value_.hh> +# include <mln/util/array.hh> +# include <mln/util/couple.hh> +# include <vector> +# include <map> + + +namespace mln +{ + + namespace accu + { + + + /// Computes the most represented label in a component. + /// The parameter \c L1 is the label type of the component in the + /// first label image. + /// The parameter \c L2 is the label type in the second label image. + template <typename L1, typename L2> + struct label_maj +// : public mln::accu::internal::base< util::array<util::couple<L2,float> >, +// label_maj<L1,L2> > + { + typedef L2 argument; + + label_maj(); + label_maj(unsigned nlabels); + + /// Manipulators. + /// \{ + void init(); + void take(const L1& l, const L2& L); + void take(const label_maj<L1,L2>& other); + /// \} + + /// Get the value of the accumulator. + util::array< util::couple<L2,float> > to_result() const; + + //operator L2 () const; + + /// Check whether this accu is able to return a result. + /// Always true here. + bool is_valid() const; + + util::array< util::couple<L2,float> > finalize_() const; + + const util::array<std::map<L2,unsigned> >& maj_array_() const; + + protected: + util::array<std::map<L2,unsigned> > maj_; + + }; + +# ifndef MLN_INCLUDE_ONLY + + template <typename L1, typename L2> + inline + label_maj<L1,L2>::label_maj() + { + } + + template <typename L1, typename L2> + inline + label_maj<L1,L2>::label_maj(unsigned nlabels) + : maj_(nlabels + 1) // Do not forget to count the background label. + { + } + + template <typename L1, typename L2> + inline + void + label_maj<L1,L2>::init() + { + } + + template <typename L1, typename L2> + inline + void + label_maj<L1,L2>::take(const L1& l, const L2& L) + { + if (maj_[l].find(L) != maj_[l].end()) + maj_[l][static_cast<unsigned>(L)] += 1; + else + maj_[l][static_cast<unsigned>(L)] = 1; + } + + template <typename L1, typename L2> + inline + void + label_maj<L1,L2>::take(const label_maj<L1,L2>& other) + { + //FIXME + abort(); + } + + template <typename L1, typename L2> + inline + util::array< util::couple<L2,float> > + label_maj<L1,L2>::finalize_() const + { + util::array< util::couple<L2,float> > p(maj_.nelements()); + for (unsigned i = 1; i < maj_.nelements(); ++i) + { + L2 + maj_l = literal::zero; + unsigned + maj_card = 0, + total_card = 0; + + for (typename std::map<L2,unsigned>::const_iterator it = maj_[i].begin(); + it != maj_[i].end(); ++it) + { + if (maj_card < it->second) + { + maj_l = it->first; + maj_card = it->second; + } + total_card += it->second; + } + + p[i] = make::couple(maj_l, maj_card / static_cast<float>(total_card)); + } + + return p; + } + + template <typename L1, typename L2> + inline + const util::array<std::map<L2,unsigned> >& + label_maj<L1,L2>::maj_array_() const + { + return maj_; + } + + + template <typename L1, typename L2> + inline + util::array< util::couple<L2,float> > + label_maj<L1,L2>::to_result() const + { + return finalize_(); + } + + template <typename L1, typename L2> + inline + bool + label_maj<L1,L2>::is_valid() const + { + return maj_.nelements() > 0; + } + +# endif // ! MLN_INCLUDE_ONLY + + } // end of namespace mln::accu + +} // end of namespace mln + + +#endif // ! MLN_ACCU_LABEL_MAJ_H _HH diff --git a/milena/sandbox/icdar/2009/hsc/lines_to_words.cc b/milena/sandbox/icdar/2009/hsc/lines_to_words.cc new file mode 100644 index 0000000..cd4b1c3 --- /dev/null +++ b/milena/sandbox/icdar/2009/hsc/lines_to_words.cc @@ -0,0 +1,98 @@ +#include <mln/core/image/image2d.hh> +#include <mln/core/alias/neighb2d.hh> +#include <mln/value/int_u8.hh> +#include <mln/value/label_8.hh> +#include <mln/value/label_16.hh> +#include <mln/io/pgm/all.hh> +#include <mln/io/pbm/all.hh> +#include <mln/io/ppm/all.hh> +#include <mln/accu/bbox.hh> +#include <mln/labeling/compute.hh> +#include <mln/pw/all.hh> +#include <mln/core/image/image_if.hh> +#include <mln/data/fill.hh> +#include <mln/core/routine/extend.hh> +#include <mln/transform/distance_geodesic.hh> +#include <mln/win/disk2d.hh> +#include <mln/morpho/watershed/flooding.hh> +#include <mln/morpho/closing/structural.hh> +#include <mln/transform/distance_geodesic.hh> +#include <mln/core/image/extended.hh> +#include <mln/core/var.hh> +#include <mln/level/convert.hh> +#include <mln/level/compute.hh> +#include <mln/accu/count_labels.hh> +#include <mln/labeling/relabel.hh> +#include <mln/labeling/wrap.hh> +#include <mln/core/routine/extend.hh> +#include <mln/morpho/watershed/superpose.hh> + +void usage(char* argv[]) +{ + std::cerr << "usage: " << argv[0] << "lines.pgm nlines output.pgm" << std::endl + << " HSC @ ICDAR'2009" << std::endl + << " Split lines into words." << std::endl + << " input.pbm: input 2D binary image (text is black; background is white)" << std::endl + << " lines.pgm: output image where line components are labeled (int_u8)" << std::endl + << " 0 is the background label." << std::endl + << " output.pgm: output image where line components 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 namespace mln::value; + + if (argc < 4) + usage(argv); + + image2d<bool> input; + io::pbm::load(input, argv[1]); + + image2d<int_u8> lines_; + io::pgm::load(lines_, argv[2]); + image2d<label_16> lines = level::convert(label_16(), lines_); + + unsigned delta = 10; + + label_16 nlines; + labeling::relabel_inplace(lines, nlines); + + + std::cout << "nlines = " << nlines << std::endl; + util::array<box2d> bboxes = labeling::compute(accu::meta::bbox(), lines, nlines); + + std::cout << "BBoxes computed" << std::endl; + + for (unsigned i = 1; i < nlines; ++i) + { + std::cout << "* Processing line " << i << std::endl; + typedef image2d<bool> line_t; + line_t line = duplicate((pw::value(lines) == i) | (lines | bboxes[i]).domain()); +// io::pbm::save(line, "l2w_line.pbm"); + + box2d b = geom::bbox(line); + b.enlarge(delta); + + mln_VAR(line_ext, extended_to(extend(line,false),b)); + +// io::pbm::save(line_ext, "l2w_line_ext.pbm"); + + std::cout << " Distance geodesic" << std::endl; + mln_VAR(line_dmap, transform::distance_geodesic(line_ext, c4(), mln_max(unsigned))); + + std::cout << " closing structural" << std::endl; + mln_VAR(line_clo, morpho::closing::structural(line_dmap, win::disk2d(21))); + + + std::cout << " Watershed" << std::endl; + label_16 nwords; + mln_VAR(wst, morpho::watershed::flooding(line_clo, c4(), nwords)); + +// io::ppm::save(morpho::watershed::superpose(input | bboxes[i], wst), "l2w_wst.ppm"); +// abort(); + } +} -- 1.5.6.5
participants (1)
-
Guillaume Lazzara