00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #ifndef OLENA_MORPHO_EXTREMA_KILLER_HH
00029 # define OLENA_MORPHO_EXTREMA_KILLER_HH
00030
00031 # include <oln/config/system.hh>
00032 # include <oln/basics2d.hh>
00033 # include <ntg/all.hh>
00034 # include <oln/morpho/extrema.hh>
00035 # include <oln/arith/ops.hh>
00036 # include <oln/morpho/watershed.hh>
00037
00038 # include <oln/level/connected.hh>
00039 # include <oln/level/lut.hh>
00040
00041 # include <oln/level/fill.hh>
00042
00043 # include <set>
00044 # include <algorithm>
00045
00046
00047 namespace oln {
00048
00049 namespace morpho {
00050
00061 template<class I, class N>
00062 typename mute<I, ntg::bin>::ret
00063 internal_kill_cc_area(const abstract::binary_image_with_dim<2, I>& input,
00064 const unsigned int area,
00065 const abstract::neighborhood<N>& Ng)
00066 {
00067 typename mute<I, ntg::int_u<20> >::ret cc = level::connected_component<ntg::int_u<20> >(input, Ng);
00068
00069 ntg::int_u<20> max_label = 0;
00070 image2d<ntg::int_u<20> >::iter_type p(cc);
00071 for_all(p)
00072 if (cc[p] > max_label)
00073 max_label = cc[p];
00074 level::hlut_def<ntg::int_u<20> > region_area;
00075 for_all(p)
00076 region_area.set(cc[p], ntg::cast::force<ntg::int_u<20> >(region_area(cc[p]) + 1));
00077 image2d<ntg::bin> output(input.size());
00078 for_all(p)
00079 if (input[p] == true)
00080 {
00081 if (region_area(cc[p]) >= ntg::int_u<20> (area))
00082 output[p] = true;
00083 else
00084 output[p] = false;
00085 }
00086 else
00087 output[p] = false;
00088 return output;
00089 }
00090
00091
00092
00093
00130 template<class I, class N>
00131 oln_concrete_type(I)
00132 sure_maxima_killer(const abstract::non_vectorial_image<I>& input,
00133 const unsigned int area,
00134 const abstract::neighborhood<N>& Ng)
00135 {
00136 mlc::eq<I::dim, N::dim>::ensure();
00137 typedef typename mute<I, ntg::bin >::ret ima_bin_type;
00138
00139 ima_bin_type* cc_level_sets = new (image2d<ntg::bin> [256]);
00140 for (unsigned int i=0; i <= 255; ++i)
00141 {
00142 image2d<ntg::bin> level_sets_i(input.size());
00143 image2d<ntg::int_u8>::iter_type p(input);
00144 for_all(p)
00145 if (input[p] >=oln_value_type(I) (i))
00146 level_sets_i[p] = true;
00147 else
00148 level_sets_i[p] = false;
00149 cc_level_sets[i] = internal_kill_cc_area(level_sets_i, area, Ng);
00150 }
00151 image2d<ntg::int_u8> output(input.size());
00152 for (int i=0; i < 255 ; ++i)
00153 {
00154 image2d<ntg::int_u8>::iter_type p(input);
00155 for_all(p)
00156 {
00157 if ((cc_level_sets[i])[p] == true)
00158 output[p] = i;
00159 }
00160 }
00161 delete[] cc_level_sets;
00162
00163 return output;
00164 }
00165
00166
00203 template<class I, class N>
00204 image2d<ntg::int_u8>
00205 sure_minima_killer(const abstract::non_vectorial_image<I>& input,
00206 const unsigned int area,
00207 const abstract::neighborhood<N>& Ng)
00208 {
00209 mlc::eq<I::dim, N::dim>::ensure();
00210
00211 typedef image2d<ntg::bin> ima_bin_type;
00212
00213 ima_bin_type* cc_level_sets = new (image2d<ntg::bin> [256]);
00214 for (unsigned int i=0; i <= 255; ++i)
00215 {
00216 image2d<ntg::bin> level_sets_i(input.size());
00217 image2d<ntg::int_u8>::iter_type p(input);
00218 for_all(p)
00219 if (input[p] <=oln_value_type(I) (i))
00220 level_sets_i[p] = true;
00221 else
00222 level_sets_i[p] = false;
00223 cc_level_sets[i] = internal_kill_cc_area(level_sets_i, area, Ng);
00224 }
00225 image2d<ntg::int_u8> output(input.size());
00226 for (int i=255; i >= 0 ; --i)
00227 {
00228 image2d<ntg::int_u8>::iter_type p(input);
00229 for_all(p)
00230 {
00231 if ((cc_level_sets[i])[p] == true)
00232 output[p] = i;
00233 }
00234 }
00235 delete[] cc_level_sets;
00236
00237 return output;
00238 }
00239
00240
00241
00242
00243
00244
00257 template<class P, class I, class N>
00258
00259 static bool
00260 is_a_strict_minimum(const abstract::point<P>& p,
00261 const abstract::non_vectorial_image<I>& input,
00262 const abstract::neighborhood<N>& Ng)
00263 {
00264 mlc::eq<I::dim, N::dim>::ensure();
00265 mlc::eq<P::dim, N::dim>::ensure();
00266
00267 bool is_p_lower = true;
00268 bool is_p_at_least_one_stricly_lower = false;
00269 oln_neighb_type(N) p_prime(Ng, p);
00270 for_all(p_prime) if (input.hold(p_prime))
00271 {
00272 if (input[p] < input[p_prime])
00273 is_p_at_least_one_stricly_lower = true;
00274 if (input[p] > input[p_prime])
00275 is_p_lower = false;
00276 }
00277 return (is_p_lower && is_p_at_least_one_stricly_lower);
00278 }
00279
00292 template<class P, class I, class N>
00293
00294 static bool
00295 is_a_strict_maximum(const abstract::point<P>& p,
00296 const abstract::non_vectorial_image<I>& input,
00297 const abstract::neighborhood<N>& Ng)
00298 {
00299 mlc::eq<I::dim, N::dim>::ensure();
00300 mlc::eq<P::dim, N::dim>::ensure();
00301
00302 bool is_p_upper = true;
00303 bool is_p_at_least_one_stricly_upper = false;
00304 oln_neighb_type(N) p_prime(Ng, p);
00305 for_all(p_prime) if (input.hold(p_prime))
00306 {
00307 if (input[p] > input[p_prime])
00308 is_p_at_least_one_stricly_upper = true;
00309 if (input[p] < input[p_prime])
00310 is_p_upper = false;
00311 }
00312 return (is_p_upper && is_p_at_least_one_stricly_upper);
00313 }
00314
00315
00357 template<class I, class N>
00358 oln_concrete_type(I)
00359 fast_minima_killer(const abstract::non_vectorial_image<I>& input,
00360 const unsigned int area,
00361 const abstract::neighborhood<N>& Ng)
00362 {
00363 mlc::eq<I::dim, N::dim>::ensure();
00364
00365 std::vector<oln_point_type(I)> cur_minimum;
00366 cur_minimum.reserve(15000);
00367 oln_concrete_type(I) working_input = input.clone();
00368 typename mute<I, ntg::bin>::ret not_processed_map(input.size());
00369 level::fill(not_processed_map, true);
00370
00371
00372 oln_iter_type(I) p(working_input);
00373 for_all(p)
00374 {
00375 if (is_a_strict_minimum(p.cur(), working_input, Ng)
00376 && not_processed_map[p])
00377 {
00378 cur_minimum.push_back(p);
00379 oln_value_type(I) lambda = working_input[p];
00380
00381
00382 typename mute<I, ntg::bin>::ret is_visited(input.size());
00383 level::fill(is_visited, false);
00384 is_visited[p] = true;
00385
00386 bool go_on = true;
00387 while (go_on)
00388 {
00389 typedef oln_value_type(I) I_type;
00390 oln_point_type(I) arg_min = p;
00391 oln_value_type(I) min = ntg_max_val(I_type);
00392 for (unsigned i = 0; i < cur_minimum.size(); ++i)
00393 {
00394 oln_neighb_type(N) p_prime(Ng, cur_minimum[i]);
00395 for_all(p_prime) if (working_input.hold(p_prime) &&
00396 (is_visited[p_prime] == false))
00397 {
00398 if (working_input[p_prime] <= min)
00399 {
00400 min = working_input[p_prime];
00401 arg_min = p_prime;
00402 }
00403 }
00404 }
00405
00406 if (working_input[arg_min] >= lambda)
00407 {
00408
00409 if (cur_minimum.size() < area)
00410 {
00411 lambda = working_input[arg_min];
00412 cur_minimum.push_back(arg_min);
00413 is_visited[arg_min] = true;
00414
00415 }
00416 else
00417 {
00418 go_on = false;
00419
00420 }
00421 }
00422 else
00423 {
00424 go_on = false;
00425 }
00426 }
00427
00428
00429 for (unsigned i = 0; i < cur_minimum.size(); ++i)
00430 {
00431 working_input[cur_minimum[i]] = lambda;
00432 not_processed_map[cur_minimum[i]] = false;
00433 }
00434 cur_minimum.erase(cur_minimum.begin(), cur_minimum.end());
00435
00436
00437 }
00438
00439 }
00440 return working_input;
00441 }
00442
00484 template<class I, class N>
00485 oln_concrete_type(I)
00486 fast_maxima_killer(const abstract::non_vectorial_image<I>& input,
00487 const unsigned int area,
00488 const abstract::neighborhood<N>& Ng)
00489 {
00490 mlc::eq<I::dim, N::dim>::ensure();
00491
00492 std::vector<oln_point_type(I)> cur_maximum;
00493 oln_concrete_type(I) working_input = input.clone();
00494 typename mute<I, ntg::bin>::ret not_processed_map(input.size());
00495 level::fill(not_processed_map, true);
00496
00497
00498 oln_iter_type(I) p(working_input);
00499 for_all(p)
00500 {
00501 if (is_a_strict_maximum(p.cur(), working_input, Ng)
00502 && not_processed_map[p])
00503 {
00504 cur_maximum.push_back(p);
00505 oln_value_type(I) lambda = working_input[p];
00506
00507 typename mute<I, ntg::bin>::ret is_visited(input.size());
00508 level::fill(is_visited, false);
00509 is_visited[p] = true;
00510
00511 bool go_on = true;
00512 while (go_on)
00513 {
00514 typedef oln_value_type(I) I_type;
00515 oln_point_type(I) arg_max = p;
00516 oln_value_type(I) max = ntg_min_val(I_type);
00517 for (unsigned i = 0; i < cur_maximum.size(); ++i)
00518 {
00519 oln_neighb_type(N) p_prime(Ng, cur_maximum[i]);
00520 for_all(p_prime) if (working_input.hold(p_prime) &&
00521 (is_visited[p_prime] == false))
00522 {
00523 if (working_input[p_prime] >= max)
00524 {
00525 max = working_input[p_prime];
00526 arg_max = p_prime;
00527 }
00528 }
00529 }
00530
00531 if (working_input[arg_max] <= lambda)
00532 {
00533
00534 if (cur_maximum.size() < area)
00535 {
00536 lambda = working_input[arg_max];
00537 cur_maximum.push_back(arg_max);
00538 is_visited[arg_max] = true;
00539
00540 }
00541 else
00542 {
00543 go_on = false;
00544
00545 }
00546 }
00547 else
00548 {
00549 go_on = false;
00550
00551 }
00552 }
00553
00554
00555 for (unsigned i = 0; i < cur_maximum.size(); ++i)
00556 {
00557
00558 working_input[cur_maximum[i]] = lambda;
00559 not_processed_map[cur_maximum[i]] = false;
00560 }
00561 cur_maximum.erase(cur_maximum.begin(), cur_maximum.end());
00562
00563
00564 }
00565
00566 }
00567 return working_input;
00568 }
00569 }
00570 }
00571 #endif