26 #ifndef SCRIBO_POSTPROCESSING_FILL_OBJECT_HOLES_HH
27 # define SCRIBO_POSTPROCESSING_FILL_OBJECT_HOLES_HH
39 # include <mln/core/image/image2d.hh>
40 # include <mln/core/alias/neighb2d.hh>
41 # include <mln/core/routine/extend.hh>
42 # include <mln/core/image/dmorph/extended.hh>
44 # include <mln/data/fill.hh>
45 # include <mln/data/transform.hh>
47 # include <mln/extension/duplicate.hh>
48 # include <mln/extension/adjust_fill.hh>
50 # include <mln/draw/box_plain.hh>
51 # include <mln/util/array.hh>
53 # include <mln/accu/math/count.hh>
55 # include <mln/fun/i2v/array.hh>
57 # include <mln/value/int_u16.hh>
59 # include <mln/labeling/blobs_and_compute.hh>
61 # include <mln/logical/not.hh>
63 # include <mln/transform/influence_zone_geodesic.hh>
65 # include <scribo/core/macros.hh>
66 # include <scribo/core/object_groups.hh>
67 # include <scribo/primitive/group/apply.hh>
73 namespace postprocessing
93 # ifndef MLN_INCLUDE_ONLY
105 return parent.
element(x) = my_find_root(parent,
110 template <
typename L>
112 compute_bboxes_image(const component_set<L>&
components)
114 typedef mln_psite(L) P;
115 typedef mln_dpsite(P) D;
120 mln_concrete(L) output;
121 initialize(output, lbl);
124 for_all_comps(i, components)
125 if (components(i).is_valid())
127 mln_box(L) b = components(i).
bbox();
131 nrows = b.pmax().row() - b.pmin().row() + 1,
132 ncols = b.pmax().col() - b.pmin().col() + 1,
133 row_offset = lbl.delta_offset(D(+1, -
ncols));
135 mln_value(L) *ptr = &output(b.pmin());
136 for (
unsigned row = 0; row <
nrows; ++row, ptr += row_offset)
137 for (
unsigned col = 0; col < ncols; ++col)
159 template <
typename L>
165 mln_trace(
"scribo::postprocessing::impl::generic::fill_object_holes");
177 value::next(components.nelements()), 0);
179 value::next(components.nelements()),
false);
182 to_keep(value::next(components.nelements()),
false);
184 const L& lbl = components.labeled_image();
200 bboxes_ima = internal::compute_bboxes_image(components);
210 mln_bkd_pixter(
const L) pxl(lbl);
213 unsigned p = pxl.offset();
214 if (bboxes_ima.element(p) == 0 || lbl.element(p) != literal::zero)
218 for (
unsigned i = 0; i < n_nbhs; ++i)
220 unsigned n = p + dp[i];
221 if (bboxes_ima.element(n) == 0 || lbl.element(n) != literal::zero)
224 unsigned r = internal::my_find_root(parent, n);
239 mln_fwd_pixter(
const L) pxl(bboxes_ima);
242 unsigned p = pxl.offset();
246 unsigned& parent_p = parent.
element(p);
249 parent_p = parent.
element(parent_p);
251 if (card.
element(p) < min_size)
260 && bboxes_ima.element(p) != literal::zero)
262 mln_value(L) group_id = bboxes_ima.element(p);
263 if (!bg_comps_done(group_id) && components(group_id).is_valid())
265 if (bg_comps(group_id) == 0)
267 bg_comps(group_id) = parent_p;
269 else if (bg_comps(group_id) != parent_p)
271 bg_comps_done(group_id) =
true;
272 to_keep(group_id) =
true;
279 if (kept == components.nelements())
281 return groups.duplicate();
284 object_groups<L> output = groups.duplicate();
285 for_all_groups(c, groups)
286 if (! to_keep(groups(c)))
303 template <typename L>
309 mln_trace(
"scribo::postprocessing::fill_object_holes");
311 mln_precondition(groups.is_valid());
320 template <
typename I>
325 mln_trace(
"scribo::postprocessing::fill_object_holes");
327 const I& input =
exact(input_);
329 mln_precondition(input.is_valid());
330 mlc_is(mln_value(I),
bool)::check();
334 typedef
value::int_u16 L;
335 typedef mln_ch_value(I, L) Li;
336 typedef accu::math::count<mln_site(Li)> A;
339 mln::util::couple<Li,
341 mln::util::array<
unsigned>,
342 mln::util::array<A> > > res_t;
348 res_t res =
labeling::blobs_and_compute(input,
c8(), nlabels, A());
350 mln::util::array<
unsigned>& holes_card = res.second().first();
351 mln_ch_value(I,
unsigned)
358 I input_i = logical::
not_(input);
359 res =
labeling::blobs_and_compute(input_i, c8(), nlabels, A());
361 mln::util::array<
unsigned>& card = res.second().first();
362 for (
unsigned i = 1; i < card.size(); ++i)
363 card(i) =
unsigned(
round(card(i) * ratio));
365 mln_ch_value(I,
unsigned)
374 initialize(hole_mask, holes);
376 mln_piter(I) p(input.domain());
379 hole_mask(p) = holes(p) < thres(p);
391 # endif // ! MLN_INCLUDE_ONLY
398 #endif // ! SCRIBO_POSTPROCESSING_FILL_OBJECT_HOLES_HH