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_RECONSTRUCTION_HH
00029 # define OLENA_MORPHO_RECONSTRUCTION_HH
00030
00031 # include <oln/basics.hh>
00032 # include <oln/convert/conversion_ng_se.hh>
00033 # include <oln/level/compare.hh>
00034 # include <oln/morpho/geodesic_dilation.hh>
00035 # include <oln/morpho/geodesic_erosion.hh>
00036 # include <oln/morpho/splitse.hh>
00037 # include <oln/morpho/stat.hh>
00038
00039 # include <ntg/basics.hh>
00040
00041 # include <queue>
00042
00043 namespace oln {
00044 namespace morpho {
00045 namespace sure {
00094 template<class I1, class I2, class N>
00095 oln_concrete_type(I1)
00096 geodesic_reconstruction_dilation(const abstract::non_vectorial_image<I1> & marker,
00097 const abstract::non_vectorial_image<I2> & mask,
00098 const abstract::neighborhood<N>& Ng)
00099 {
00100 mlc::eq<I1::dim, I2::dim>::ensure();
00101 mlc::eq<I1::dim, N::dim>::ensure();
00102 precondition(marker.size() == mask.size());
00103 precondition(level::is_greater_or_equal(mask, marker));
00104 oln_concrete_type(I1) output = marker.clone();
00105 bool non_stability = true;
00106 while (non_stability)
00107 {
00108 oln_concrete_type(I1) work = geodesic_dilation(output, mask, Ng);
00109 non_stability = !(level::is_equal(work, output));
00110 output = work;
00111 }
00112 return output;
00113 }
00114 }
00115
00116
00117 namespace sequential {
00166 template<class I1, class I2, class N>
00167 oln_concrete_type(I1)
00168 geodesic_reconstruction_dilation(const abstract::non_vectorial_image<I1> & marker,
00169 const abstract::non_vectorial_image<I2> & mask,
00170 const abstract::neighborhood<N>& Ng)
00171 {
00172 mlc::eq<I1::dim, I2::dim>::ensure();
00173 mlc::eq<I1::dim, N::dim>::ensure();
00174 precondition(marker.size() == mask.size());
00175 precondition(level::is_greater_or_equal(mask, marker));
00176
00177
00178 typedef typename abstract::neighborhood<N>::win_type E;
00179 E se_plus = get_plus_se_p(convert::ng_to_cse(Ng));
00180 E se_minus = get_minus_se_p(convert::ng_to_cse(Ng));
00181
00182 oln_concrete_type(I1) output = marker.clone();
00183 bool non_stability = true;
00184 typename I1::fwd_iter_type fwd_p(output);
00185 typename I1::bkd_iter_type bkd_p(output);
00186 while (non_stability)
00187 {
00188 oln_concrete_type(I1) work = output.clone();
00189 work.border_adapt_copy(Ng.delta());
00190 for_all (fwd_p)
00191 work[fwd_p] = ntg::min(morpho::max(work, fwd_p, se_plus), mask[fwd_p]);
00192 for_all (bkd_p)
00193 work[bkd_p] = ntg::min(morpho::max(work, bkd_p, se_minus), mask[bkd_p]);
00194 non_stability = !(level::is_equal(work, output));
00195 output = work;
00196 }
00197 return output;
00198 }
00199 }
00200
00201
00202 namespace hybrid {
00203
00204 namespace internal {
00205
00214 template<class P, class I1, class I2, class E> inline
00215 static bool
00216 exist_init_dilation(const abstract::point<P>& p,
00217 const abstract::non_vectorial_image<I1>& marker,
00218 const abstract::non_vectorial_image<I2>& mask,
00219 const abstract::struct_elt<E>& se)
00220 {
00221 mlc::eq<I1::dim, I2::dim>::ensure();
00222 mlc::eq<I1::dim, E::dim>::ensure();
00223 mlc::eq<I1::dim, P::dim>::ensure();
00224
00225 oln_neighb_type(E) q(se, p);
00226 for_all (q)
00227 if (marker.hold(q) && (marker[q] < marker[p]) && (marker[q] < mask[q]))
00228 return true;
00229 return false;
00230 }
00231
00232 }
00233
00282 template<class I1, class I2, class N>
00283 oln_concrete_type(I1)
00284 geodesic_reconstruction_dilation(const abstract::non_vectorial_image<I1> & marker,
00285 const abstract::non_vectorial_image<I2> & mask,
00286 const abstract::neighborhood<N>& Ng)
00287 {
00288 mlc::eq<I1::dim, I2::dim>::ensure();
00289 mlc::eq<I1::dim, N::dim>::ensure();
00290
00291 precondition(marker.size() == mask.size());
00292 precondition(level::is_greater_or_equal(mask, marker));
00293
00294 oln_concrete_type(I1) output = marker.clone();
00295 output.border_adapt_copy(Ng.delta());
00296 {
00297 typedef typename abstract::neighborhood<N>::win_type E;
00298 E Ng_plus = get_plus_se_p(convert::ng_to_cse(Ng));
00299 E Ng_minus = get_minus_se_p(convert::ng_to_cse(Ng));
00300 typename I1::fwd_iter_type fwd_p(output);
00301 typename I1::bkd_iter_type bkd_p(output);
00302 for_all (fwd_p)
00303 output[fwd_p] = ntg::min(morpho::max(output, fwd_p, Ng_plus),
00304 mask[fwd_p]);
00305
00306 std::queue<oln_point_type(I1) > fifo;
00307 for_all (bkd_p)
00308 {
00309 output[bkd_p] = ntg::min(morpho::max(output, bkd_p, Ng_minus),
00310 mask[bkd_p]);
00311 if (internal::exist_init_dilation(bkd_p.cur(), output, mask, Ng_minus))
00312 fifo.push(bkd_p);
00313 }
00314
00315 while (!fifo.empty())
00316 {
00317 oln_point_type(I1) p = fifo.front();
00318 fifo.pop();
00319 oln_neighb_type(N) q(Ng, p);
00320 for_all (q) if (output.hold(q))
00321 {
00322 if ((output[q] < output[p]) && (mask[q] != output[q]))
00323 {
00324 output[q] = ntg::min(output[p], mask[q]);
00325 fifo.push(q);
00326 }
00327 }
00328 }
00329 }
00330 return output;
00331 }
00332 }
00333
00334
00335
00336
00337 namespace sure {
00338
00387 template<class I1, class I2, class N>
00388 oln_concrete_type(I1)
00389 geodesic_reconstruction_erosion(const abstract::non_vectorial_image<I1> & marker,
00390 const abstract::non_vectorial_image<I2> & mask,
00391 const abstract::neighborhood<N>& Ng)
00392 {
00393 mlc::eq<I1::dim, I2::dim>::ensure();
00394 mlc::eq<I1::dim, N::dim>::ensure();
00395 precondition(marker.size() == mask.size());
00396 precondition(level::is_greater_or_equal(marker, mask));
00397 oln_concrete_type(I1) output = marker.clone();
00398 bool non_stability = true;
00399 while (non_stability)
00400 {
00401 oln_concrete_type(I1) work = geodesic_erosion(output, mask, Ng);
00402 non_stability = !(level::is_equal(work, output));
00403 output = work;
00404 }
00405 return output;
00406 }
00407 }
00408
00409
00410 namespace sequential {
00411
00460 template<class I1, class I2, class N>
00461 oln_concrete_type(I1)
00462 geodesic_reconstruction_erosion(const abstract::non_vectorial_image<I1>& marker,
00463 const abstract::non_vectorial_image<I2>& mask,
00464 const abstract::neighborhood<N>& Ng)
00465 {
00466 mlc::eq<I1::dim, I2::dim>::ensure();
00467 mlc::eq<I1::dim, N::dim>::ensure();
00468 precondition(marker.size() == mask.size());
00469 precondition(level::is_greater_or_equal(marker, mask));
00470
00471 typedef typename abstract::neighborhood<N>::win_type E;
00472 E se_plus = get_plus_se_p(convert::ng_to_cse(Ng));
00473 E se_minus = get_minus_se_p(convert::ng_to_cse(Ng));
00474 oln_concrete_type(I1) output = marker.clone();
00475
00476 bool non_stability = true;
00477 typename I1::fwd_iter_type fwd_p(output);
00478 typename I1::bkd_iter_type bkd_p(output);
00479 while (non_stability)
00480 {
00481 oln_concrete_type(I1) work = output.clone();
00482 work.border_adapt_copy(Ng.delta());
00483 for_all (fwd_p)
00484 work[fwd_p] = ntg::max(morpho::min(work, fwd_p, se_plus), mask[fwd_p]);
00485 for_all (bkd_p)
00486 work[bkd_p] = ntg::max(morpho::min(work, bkd_p, se_minus), mask[bkd_p]);
00487 non_stability = !(level::is_equal(work, output));
00488 output = work;
00489 }
00490 return output;
00491 }
00492 }
00493
00494
00495 namespace hybrid {
00496 namespace internal {
00505 template<class P, class I1, class I2, class E> inline
00506 static bool
00507 exist_init_erosion(const abstract::point<P>& p,
00508 const abstract::non_vectorial_image<I1>& marker,
00509 const abstract::non_vectorial_image<I2>& mask,
00510 const abstract::struct_elt<E>& se)
00511 {
00512 mlc::eq<I1::dim, I2::dim>::ensure();
00513 mlc::eq<I1::dim, E::dim>::ensure();
00514 mlc::eq<I1::dim, P::dim>::ensure();
00515
00516 oln_neighb_type(E) q(se, p);
00517 for_all (q)
00518 if (marker.hold(q) && (marker[q] > marker[p]) && (marker[q] > mask[q]))
00519 return true;
00520 return false;
00521 }
00522 }
00523
00572 template<class I1, class I2, class N>
00573 oln_concrete_type(I1)
00574 geodesic_reconstruction_erosion(const abstract::non_vectorial_image<I1> & marker,
00575 const abstract::non_vectorial_image<I2> & mask,
00576 const abstract::neighborhood<N>& Ng)
00577 {
00578 mlc::eq<I1::dim, I2::dim>::ensure();
00579 mlc::eq<I1::dim, N::dim>::ensure();
00580
00581 precondition(marker.size() == mask.size());
00582 precondition(level::is_greater_or_equal(marker, mask));
00583
00584 oln_concrete_type(I1) output = marker.clone();
00585 output.border_adapt_copy(Ng.delta());
00586 {
00587 typedef typename abstract::neighborhood<N>::win_type E;
00588 E Ng_plus = get_plus_se_p(convert::ng_to_cse(Ng));
00589 E Ng_minus = get_minus_se_p(convert::ng_to_cse(Ng));
00590 typename I1::fwd_iter_type fwd_p(output);
00591 typename I1::bkd_iter_type bkd_p(output);
00592 for_all (fwd_p)
00593 output[fwd_p] = ntg::max(morpho::min(output, fwd_p, Ng_plus),
00594 mask[fwd_p]);
00595
00596 std::queue<oln_point_type(I1) > fifo;
00597 for_all (bkd_p)
00598 {
00599 output[bkd_p] = ntg::max(morpho::min(output, bkd_p, Ng_minus),
00600 mask[bkd_p]);
00601 if (internal::exist_init_erosion(bkd_p.cur(), output, mask, Ng_minus))
00602 fifo.push(bkd_p);
00603 }
00604
00605 while (!fifo.empty())
00606 {
00607 oln_point_type(I1) p = fifo.front();
00608 fifo.pop();
00609 oln_neighb_type(N) q(Ng, p);
00610 for_all (q) if (output.hold(q))
00611 {
00612 if ((output[q] > output[p]) && (mask[q] != output[q]))
00613 {
00614 output[q] = ntg::max(output[p], mask[q]);
00615 fifo.push(q);
00616 }
00617 }
00618 }
00619 }
00620 return output;
00621 }
00622
00623
00624 }
00625 }
00626 }
00627
00628 #endif // OLENA_MORPHO_RECONSTRUCTION_HH