--- scribo/ChangeLog | 12 ++- .../fill_object_holes.hh} | 134 ++++++++++++++++---- 2 files changed, 118 insertions(+), 28 deletions(-) copy scribo/{filter/object_groups_with_holes.hh => postprocessing/fill_object_holes.hh} (65%)
diff --git a/scribo/ChangeLog b/scribo/ChangeLog index 4aa545d..97f15b8 100644 --- a/scribo/ChangeLog +++ b/scribo/ChangeLog @@ -1,11 +1,15 @@ 2010-04-30 Guillaume Lazzara z@lrde.epita.fr
+ * postprocessing/fill_object_holes.hh: New routine. + +2010-04-30 Guillaume Lazzara z@lrde.epita.fr + Add new routines to detect separators.
- * scribo/primitive/extract/horizontal_separators.hh, - * scribo/primitive/extract/separators.hh, - * scribo/primitive/extract/vertical_separators.hh, - * scribo/primitive/remove/separators.hh: New. + * primitive/extract/horizontal_separators.hh, + * primitive/extract/separators.hh, + * primitive/extract/vertical_separators.hh, + * primitive/remove/separators.hh: New.
2010-04-30 Guillaume Lazzara z@lrde.epita.fr
diff --git a/scribo/filter/object_groups_with_holes.hh b/scribo/postprocessing/fill_object_holes.hh similarity index 65% copy from scribo/filter/object_groups_with_holes.hh copy to scribo/postprocessing/fill_object_holes.hh index 570ae6a..4771844 100644 --- a/scribo/filter/object_groups_with_holes.hh +++ b/scribo/postprocessing/fill_object_holes.hh @@ -23,12 +23,16 @@ // exception does not however invalidate any other reasons why the // executable file might be covered by the GNU General Public License.
-#ifndef SCRIBO_FILTER_OBJECT_GROUPS_WITH_HOLES_HH -# define SCRIBO_FILTER_OBJECT_GROUPS_WITH_HOLES_HH +#ifndef SCRIBO_POSTPROCESSING_FILL_OBJECT_HOLES_HH +# define SCRIBO_POSTPROCESSING_FILL_OBJECT_HOLES_HH
/// \file /// -/// \brief Remove groups not having a minimum number of holes. +/// \brief Fill-in object small holes. + +/// \FIXME share code with filter/object_groups_with_holes.hh +/// \FIXME Merge the two following routines. +/// \FIXME Use a size ratio in both overloads.
# include <sstream>
@@ -47,28 +51,32 @@ # include <mln/fun/i2v/array.hh>
# include <scribo/core/macros.hh> -# include <scribo/core/component_set.hh> +# include <scribo/core/object_groups.hh> +# include <scribo/primitive/group/apply.hh>
namespace scribo {
- namespace filter + namespace postprocessing {
using namespace mln;
- /*! \brief Remove groups not having a minimum number of holes. + /*! \brief Fill-in object small holes.
+ */ + template <typename I> + inline + mln_concrete(I) + fill_object_holes(const Image<I>& input, float ratio);
- */ template <typename L> inline object_groups<L> - object_groups_with_holes(const object_groups<L>& components, - unsigned min_size); - + fill_object_holes(const object_groups<L>& groups, + unsigned min_size);
# ifndef MLN_INCLUDE_ONLY
@@ -124,7 +132,7 @@ namespace scribo }
- } // end of namespace scribo::filter::internal + } // end of namespace scribo::postprocessing::internal
@@ -139,10 +147,10 @@ namespace scribo template <typename L> inline object_groups<L> - object_groups_with_holes(const object_groups<L>& groups, + fill_object_holes(const object_groups<L>& groups, unsigned min_size) { - trace::entering("scribo::filter::impl::generic::object_groups_with_holes"); + trace::entering("scribo::postprocessing::impl::generic::fill_object_holes");
// Grouping groups and relabel the underlying labeled image. // Groups are now considered as components. @@ -259,7 +267,7 @@ namespace scribo
if (kept == components.nelements()) { - trace::exiting("scribo::filter::impl::generic::object_groups_with_holes"); + trace::exiting("scribo::postprocessing::impl::generic::fill_object_holes"); return groups.duplicate(); }
@@ -269,15 +277,15 @@ namespace scribo output(c) = 0;
- trace::exiting("scribo::filter::impl::generic::object_groups_with_holes"); + trace::exiting("scribo::postprocessing::impl::generic::fill_object_holes"); return output; }
}
- } // end of namespace scribo::filter::impl::generic + } // end of namespace scribo::postprocessing::impl::generic
- } // end of namespace scribo::filter::impl + } // end of namespace scribo::postprocessing::impl
@@ -286,25 +294,103 @@ namespace scribo template <typename L> inline object_groups<L> - object_groups_with_holes(const object_groups<L>& groups, - unsigned min_size) + fill_object_holes(const object_groups<L>& groups, + unsigned min_size) { - trace::entering("scribo::filter::object_groups_with_holes"); + trace::entering("scribo::postprocessing::fill_object_holes");
mln_precondition(groups.is_valid());
object_groups<L> - output = impl::generic::object_groups_with_holes(groups, min_size); + output = impl::generic::fill_object_holes(groups, min_size); + + trace::exiting("scribo::postprocessing::fill_object_holes"); + return output; + } + + + template <typename I> + inline + mln_concrete(I) + fill_object_holes(const Image<I>& input_, float ratio) + { + trace::entering("scribo::postprocessing::fill_object_holes"); + + mln_precondition(input.is_valid()); + mlc_is(mln_value(I), bool)::check(); + + const I& input = exact(input_); + mln_concrete(I) output = duplicate(input); + + typedef value::int_u16 L; + typedef mln_ch_value(I, L) Li; + typedef accu::math::count<mln_site(Li)> A; + + typedef util::couple<Li, util::couple<util::array<unsigned>, + util::array<A> > > res_t; + + // Holes card Image + + std::cout << "> Holes card image" << std::endl; + + L nlabels; + + res_t res = labeling::blobs_and_compute(input, c8(), nlabels, A());
- trace::exiting("scribo::filter::object_groups_with_holes"); + util::array<unsigned>& holes_card = res.second().first(); + mln_ch_value(I, unsigned) + holes = data::transform(res.first(), holes_card); + + + + // Threshold Image + + std::cout << "> Threshold image" << std::endl; + + + I input_i = logical::not_(input); + res = labeling::blobs_and_compute(input_i, c8(), nlabels, A()); + + util::array<unsigned>& card = res.second().first(); + for (unsigned i = 1; i < card.size(); ++i) + card(i) = card(i) * ratio; + + mln_ch_value(I, unsigned) + thres = data::transform(res.first(), card); + thres = transform::influence_zone_geodesic(thres, c8()); + + + + // Thresholding + + std::cout << "> Thresholding" << std::endl; + + I hole_mask; + initialize(hole_mask, holes); + data::fill(hole_mask, false); + mln_piter(I) p(input.domain()); + for_all(p) + if (holes(p)) + hole_mask(p) = holes(p) < thres(p); + + + // Cleanup + + std::cout << "> Cleanup" << std::endl; + + data::fill((output | pw::value(hole_mask)).rw(), false); + + + trace::exiting("scribo::postprocessing::fill_object_holes"); return output; }
+ # endif // ! MLN_INCLUDE_ONLY
- } // end of namespace scribo::filter + } // end of namespace scribo::postprocessing
} // end of namespace scribo
-#endif // ! SCRIBO_FILTER_OBJECT_GROUPS_WITH_HOLES_HH +#endif // ! SCRIBO_POSTPROCESSING_FILL_OBJECT_HOLES_HH