26 #ifndef SCRIBO_TOOLCHAIN_INTERNAL_TEXT_IN_PICTURE_FUNCTOR_HH
27 # define SCRIBO_TOOLCHAIN_INTERNAL_TEXT_IN_PICTURE_FUNCTOR_HH
38 # ifndef SCRIBO_NDEBUG
39 # include <mln/util/timer.hh>
40 # endif // ! SCRIBO_NDEBUG
42 # include <mln/core/image/image2d.hh>
43 # include <mln/core/alias/neighb2d.hh>
45 # include <mln/literal/colors.hh>
46 # include <mln/value/rgb8.hh>
48 # include <mln/fun/v2v/rgb_to_int_u.hh>
50 # include <mln/subsampling/antialiased.hh>
52 # include <scribo/core/def/lbl_type.hh>
54 # include <scribo/draw/bounding_boxes.hh>
55 # include <scribo/draw/groups_bboxes.hh>
57 # include <scribo/binarization/sauvola_ms.hh>
58 # include <scribo/binarization/sauvola.hh>
60 # include <scribo/primitive/extract/components.hh>
62 # include <scribo/primitive/link/merge_double_link.hh>
63 # include <scribo/primitive/link/with_single_left_link.hh>
64 # include <scribo/primitive/link/with_single_right_link.hh>
66 # include <scribo/primitive/group/apply.hh>
67 # include <scribo/primitive/group/from_double_link.hh>
68 # include <scribo/primitive/group/from_single_link.hh>
70 # include <scribo/primitive/regroup/from_single_left_link.hh>
72 # include <scribo/filter/object_groups_with_holes.hh>
74 # include <scribo/filter/object_links_bbox_h_ratio.hh>
75 # include <scribo/filter/object_links_bbox_overlap.hh>
77 # include <scribo/filter/object_groups_small.hh>
78 # include <scribo/filter/object_groups_mean_width.hh>
80 # include <scribo/debug/decision_image.hh>
81 # include <scribo/debug/linked_bboxes_image.hh>
83 # include <scribo/debug/logger.hh>
84 # include <scribo/debug/highlight_text_area.hh>
85 # include <scribo/debug/text_areas_image.hh>
87 # include <scribo/preprocessing/split_bg_fg.hh>
89 # include <scribo/make/debug_filename.hh>
91 # include <scribo/toolchain/internal/toolchain_functor.hh>
93 # include <scribo/afp/components.hh>
94 # include <scribo/afp/link.hh>
95 # include <scribo/afp/regroup.hh>
111 template <
typename I>
120 virtual int nsteps()
const;
132 bool enable_bg_removal;
133 bool enable_multi_scale_bin;
142 unsigned max_dim_size;
146 unsigned sauvola_min_w;
151 unsigned small_groups;
153 unsigned regroup_dmax;
154 unsigned group_min_holes;
162 # ifndef SCRIBO_NDEBUG
166 virtual void on_start();
167 virtual void on_end();
168 virtual void on_progress();
172 # endif // ! SCRIBO_NDEBUG
175 unsigned get_factor(
const I& ima,
unsigned max_dim_size);
180 # ifndef MLN_INCLUDE_ONLY
183 template <
typename I>
186 unsigned max_dim_size)
188 mln_precondition(max_dim_size != 0);
194 factor = max_dim / max_dim_size;
196 return factor ? factor : 1;
200 template <
typename I>
201 text_in_picture_functor<I>::text_in_picture_functor()
202 : enable_bg_removal(false),
203 enable_multi_scale_bin(true),
218 template <
typename I>
220 text_in_picture_functor<I>::operator()(
const Image<I>& input_rgb_orig_)
222 const I& input_rgb_orig =
exact(input_rgb_orig_);
223 mln_precondition(input_rgb_orig.is_valid());
225 using namespace scribo;
226 using namespace scribo::primitive;
233 lambda = 1.2 * (input_rgb_orig.nrows() + input_rgb_orig.ncols());
236 std::cout <<
"Using lambda = " << lambda << std::endl;
240 if (max_dim_size != 0)
242 on_new_progress_label(
"Resizing image if needed...");
244 unsigned factor = get_factor(input_rgb_orig, max_dim_size);
247 std::cout <<
"Reduction Factor : " << factor
249 <<
"Original domain: " << input_rgb_orig.domain()
253 input_rgb = mln::subsampling::
antialiased(input_rgb_orig, factor);
256 std::cout << "Resized domain: " << input_rgb.domain()
260 input_rgb = input_rgb_orig;
264 mln_ch_value(I,
value::int_u8) intensity_ima;
265 if (enable_bg_removal)
267 on_new_progress_label(
"Extracting foreground and converting to intensity image...");
271 fg = preprocessing::split_bg_fg(input_rgb, lambda, 32).second();
272 intensity_ima =
data::
transform(fg, mln::fun::v2v::rgb_to_int_u<8>());
274 # ifndef SCRIBO_NDEBUG
277 # endif // ! SCRIBO_NDEBUG
281 on_new_progress_label(
"Converting to intensity image...");
290 unsigned w = std::
min(intensity_ima.nrows() / 3, intensity_ima.
ncols() / 3);
293 w = std::
min(w, sauvola_min_w);
295 std::cout << "** Using Sauvola with w_1 = " << w << std::endl;
297 if (enable_multi_scale_bin)
299 on_new_progress_label(
"Binarizing image with multi-scale algorithm...");
304 on_new_progress_label(
"Binarizing image...");
308 # ifndef SCRIBO_NDEBUG
311 # endif // ! SCRIBO_NDEBUG
323 Obj filtered_components;
328 def::lbl_type ncomponents;
329 L components = extract_components(input, ncomponents, attribs);
331 filtered_components = Obj(components, ncomponents, attribs);
335 std::cout <<
"Object extracted " << filtered_components.nelements() <<
" components" << std::endl;
340 on_new_progress_label(
"Linking potential components");
343 links = link::left_right(filtered_components);
350 # ifndef SCRIBO_NDEBUG
353 std::cerr <<
"BEFORE - ncomponents = " << filtered_components.nelements() << std::endl;
355 scribo::debug::AuxiliaryResults,
357 left_link, right_link,
358 literal::red, literal::cyan,
364 # endif // ! SCRIBO_NDEBUG
367 on_new_progress_label(
"Validating left and right links");
370 merged_links = link::merge_double_link(left_link, right_link);
375 on_new_progress_label(
"Filtering component links.");
382 # ifndef SCRIBO_NDEBUG
388 hratio_filtered_links,
391 scribo::debug::
logger().log_image(scribo::debug::AuxiliaryResults,
392 hratio_decision_image,
393 "hratio_links_decision_image");
395 # endif // ! SCRIBO_NDEBUG
403 # ifndef SCRIBO_NDEBUG
408 hratio_filtered_links,
409 overlap_filtered_links,
412 scribo::debug::
logger().log_image(scribo::debug::AuxiliaryResults,
413 overlap_decision_image,
414 "overlap_links_decision_image");
416 # endif // ! SCRIBO_NDEBUG
421 on_new_progress_label(
"Grouping components...");
423 groups = group::from_single_link(overlap_filtered_links);
428 # ifndef SCRIBO_NDEBUG
439 filtered_components, literal::green);
440 scribo::draw::bounding_boxes(decision_image,
441 raw_group_image, literal::blue);
443 scribo::debug::
logger().log_image(scribo::debug::AuxiliaryResults,
445 "group_and_object_image");
448 scribo::draw::bounding_boxes(decision_image,
449 raw_group_image, literal::blue);
451 scribo::debug::
logger().log_image(scribo::debug::AuxiliaryResults,
455 # endif // ! SCRIBO_NDEBUG
457 on_new_progress_label(
"Filtering groups with too low cardinality...");
464 # ifndef SCRIBO_NDEBUG
466 if (scribo::debug::
logger().is_enabled())
476 "small_groups_filter");
478 # endif // ! SCRIBO_NDEBUG
482 on_new_progress_label(
"Filtering groups having components with too low thickness...");
490 # ifndef SCRIBO_NDEBUG
502 "thin_groups_filter");
504 # endif // ! SCRIBO_NDEBUG
511 on_new_progress_label(
"Regrouping groups...");
513 filtered_thin_groups = regroup::from_single_left_link(filtered_thin_groups,
520 on_new_progress_label(
"Filtering groups with too many holes...");
527 # ifndef SCRIBO_NDEBUG
538 "group_with_holes_filter");
540 # endif // ! SCRIBO_NDEBUG
543 on_new_progress_label(
"Finalizing results...");
550 std::cout <<
"# objects = " << output.nelements() << std::endl;
553 # ifndef SCRIBO_NDEBUG
559 "input_with_bboxes");
565 # endif // ! SCRIBO_NDEBUG
573 template <
typename I>
575 text_in_picture_functor<I>::nsteps()
const
581 # ifndef SCRIBO_NDEBUG
583 template <
typename I>
585 text_in_picture_functor<I>::on_start()
591 template <
typename I>
593 text_in_picture_functor<I>::on_end()
597 std::cout <<
"Total time: " << gt << std::endl;
600 template <
typename I>
602 text_in_picture_functor<I>::on_progress()
606 std::cout << t << std::endl;
611 # endif // ! SCRIBO_NDEBUG
614 # endif // ! MLN_INCLUDE_ONLY
623 #endif // SCRIBO_TOOLCHAIN_INTERNAL_TEXT_IN_PICTURE_FUNCTOR_HH