32 #ifndef SCRIBO_PRIMITIVE_EXTRACT_SEPARATORS_NONVISIBLE_HH
33 # define SCRIBO_PRIMITIVE_EXTRACT_SEPARATORS_NONVISIBLE_HH
35 # include <mln/core/concept/image.hh>
36 # include <mln/core/image/dmorph/image_if.hh>
37 # include <mln/pw/all.hh>
39 # include <mln/accu/count_value.hh>
41 # include <mln/draw/line.hh>
43 # include <mln/data/fill.hh>
44 # include <mln/data/convert.hh>
46 # include <mln/labeling/relabel.hh>
47 # include <mln/labeling/value.hh>
49 # include <mln/morpho/closing/structural.hh>
51 # include <mln/literal/colors.hh>
53 # include <mln/value/label_16.hh>
54 # include <mln/value/int_u8.hh>
55 # include <mln/value/rgb8.hh>
57 # include <mln/util/timer.hh>
59 # include <scribo/core/object_groups.hh>
60 # include <scribo/core/component_set.hh>
61 # include <scribo/core/def/lbl_type.hh>
63 # include <scribo/debug/logger.hh>
65 # include <scribo/filter/object_groups_small.hh>
66 # include <scribo/filter/object_links_bottom_aligned.hh>
67 # include <scribo/filter/object_links_top_aligned.hh>
69 # include <scribo/preprocessing/rotate_90.hh>
71 # include <scribo/primitive/extract/components.hh>
73 # include <scribo/primitive/link/internal/dmax_default.hh>
74 # include <scribo/primitive/link/with_single_right_link_dmax_ratio_aligned.hh>
75 # include <scribo/primitive/link/with_single_left_link_dmax_ratio_aligned.hh>
77 # include <scribo/primitive/group/from_double_link_any.hh>
92 using namespace scribo::debug;
100 template <
typename I>
106 # ifndef MLN_INCLUDE_ONLY
110 template <
typename I>
114 mln_trace(
"scribo::primitive::extract::separators_nonvisible");
116 const I& in =
exact(in_);
117 mln_precondition(in.is_valid());
118 typedef mln_value(I) Vi;
119 mlc_is(Vi,
bool)::check();
121 typedef scribo::def::lbl_type V;
122 typedef mln_ch_value(I,V) L;
129 bool _debug_ =
logger().is_at_level(AuxiliaryResults);
134 mln_concrete(I) input_clo = morpho::closing::
structural(in, vl);
137 logger().log_image(AuxiliaryResults, input_clo, "input_clo");
140 input_clo = scribo::preprocessing::rotate_90(input_clo, false);
151 logger().log_image(AuxiliaryResults,
157 object_links<L> top_right, bot_right;
159 object_links<L> top_left, bot_left;
162 typedef link::internal::dmax_default Dmax_F;
166 link::internal::single_right_dmax_ratio_aligned_functor<L,Dmax_F>
167 functor(
components, Dmax_F(dmax), min_angle, max_angle,
168 anchor::TopStrictLeft);
177 link::internal::single_left_dmax_ratio_aligned_functor<L,Dmax_F>
178 lfunctor(
components, Dmax_F(dmax), min_angle, max_angle,
179 anchor::TopStrictLeft);
192 | (pw::
value(lfunctor.debug_) != pw::cst(literal::black)))
193 | (pw::
value(lfunctor.debug_) != pw::cst(literal::white)), output);
195 logger().log_image(AuxiliaryResults, output, "left_right_top");
204 link::internal::single_right_dmax_ratio_aligned_functor<L,Dmax_F>
205 functor(
components, Dmax_F(dmax), min_angle, max_angle,
206 anchor::BottomStrictRight);
219 link::internal::single_left_dmax_ratio_aligned_functor<L,Dmax_F>
220 lfunctor(
components, Dmax_F(dmax), min_angle, max_angle,
221 anchor::BottomStrictRight);
233 | (pw::
value(lfunctor.debug_) != pw::cst(literal::black)))
234 | (pw::
value(lfunctor.debug_) != pw::cst(literal::white)), output);
236 logger().log_image(AuxiliaryResults, output, "left_right_bot");
243 top_groups = primitive::group::from_double_link_any(top_left, top_right);
245 bot_groups = primitive::group::from_double_link_any(bot_left, bot_right);
254 initialize(separators, input_clo);
258 extension::
fill(separators, false);
261 for_all_groups(d, top_groups)
262 if (top_groups(d).is_valid())
265 top_groups(d).
bbox().pmin(),
267 top_groups(d).
bbox().pmax().col()),
272 for_all_groups(d, bot_groups)
273 if (bot_groups(d).is_valid())
277 bot_groups(d).
bbox().pmin().col()),
278 bot_groups(d).
bbox().pmax(),
287 mln_concrete(I) input = scribo::preprocessing::rotate_90(in, false);
289 mln_ch_value(I,
value::rgb8)
292 for_all_groups(d, top_groups)
293 if (top_groups(d).is_valid())
296 top_groups(d).
bbox().pmin(),
298 top_groups(d).
bbox().pmax().col()),
302 for_all_groups(d, bot_groups)
303 if (bot_groups(d).is_valid())
307 bot_groups(d).
bbox().pmin().col()),
308 bot_groups(d).
bbox().pmax(),
324 logger().log_image(AuxiliaryResults, input_with_seps, "input_with_seps");
327 unsigned length = 25;
336 accu::count_value<
bool> accu(true);
337 typedef mln_ch_value(I,
unsigned) J;
339 J tmp = accu::transform_line(accu, input_clo, length, 1);
342 value::int_u8 nlabels;
343 mln_ch_value(I,
value::int_u8)
347 mln::util::array<
bool> relbl(
unsigned(nlabels) + 1, true);
350 unsigned invalid_ratio =
unsigned(length * 0.30f);
354 value::int_u8 *sep_lbl_ptr = sep_lbl.buffer()
355 + sep_lbl.offset_of_point(sep_lbl.domain().pmin());
356 bool *separators_ptr = separators.buffer()
357 + separators.offset_of_point(separators.domain().pmin());
358 unsigned *tmp_ptr = tmp.buffer() + tmp.offset_of_point(tmp.domain().pmin());;
359 int idx1 = tmp.delta_offset(dp1);
360 int idx2 = tmp.delta_offset(dp2);
367 row_idx_sep_lbl = sep_lbl.delta_offset(
dpoint2d(+1, - ncols)),
368 row_idx_separators = separators.delta_offset(dpoint2d(+1, - ncols)),
369 row_idx_tmp = tmp.delta_offset(dpoint2d(+1, - ncols));
371 for (
unsigned row = 0; row < nrows; ++row)
373 for (
unsigned col = 0; col <
ncols; ++col)
377 unsigned lbl = *sep_lbl_ptr;
380 top_count = *(tmp_ptr + idx1),
381 bot_count = *(tmp_ptr + idx2);
385 if (top_count >= invalid_ratio + 1
386 && bot_count >= invalid_ratio + 1)
397 tmp_ptr += row_idx_tmp;
398 sep_lbl_ptr += row_idx_sep_lbl;
399 separators_ptr += row_idx_separators;
410 "separators_filtered");
418 # endif // ! MLN_INCLUDE_ONLY
426 #endif // ! SCRIBO_PRIMITIVE_EXTRACT_SEPARATORS_NONVISIBLE_HH