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 #ifndef MLN_TOPO_SKELETON_CREST_HH
00028 # define MLN_TOPO_SKELETON_CREST_HH
00029
00033
00034 # include <mln/core/concept/image.hh>
00035 # include <mln/core/concept/neighborhood.hh>
00036 # include <mln/data/fill.hh>
00037 # include <mln/extension/adjust.hh>
00038 # include <mln/border/equalize.hh>
00039
00040
00041 namespace mln
00042 {
00043
00044 namespace topo
00045 {
00046
00047 namespace skeleton
00048 {
00049
00050
00062
00092 template <typename I, typename D, typename N>
00093 mln_concrete(I)
00094 crest(const Image<I>& input, const Image<D>& dist_map,
00095 const Neighborhood<N>& nbh, unsigned psi_threshold);
00096
00099 template <typename I, typename D, typename N>
00100 mln_concrete(I)
00101 crest(const Image<I>& input, const Image<D>& dist_map,
00102 const Neighborhood<N>& nbh);
00103
00104
00105
00106 # ifndef MLN_INCLUDE_ONLY
00107
00108
00109
00110 namespace impl
00111 {
00112
00113 namespace generic
00114 {
00115
00116 template <typename I, typename D, typename N>
00117 mln_concrete(I)
00118 crest(const Image<I>& input_, const Image<D>& dist_map_,
00119 const Neighborhood<N>& nbh_, unsigned psi_threshold)
00120 {
00121 trace::entering("topo::skeleton::impl::generic::crest");
00122 const I& input = exact(input_);
00123 const D& dist_map = exact(dist_map_);
00124 const N& nbh = exact(nbh_);
00125
00126 mlc_equal(mln_value(I), bool)::check();
00127 mln_precondition(input.is_valid());
00128 mln_precondition(dist_map.is_valid());
00129 mln_precondition(nbh.is_valid());
00130
00131 mln_concrete(I) is_crest;
00132 initialize(is_crest, input);
00133 data::fill(is_crest, false);
00134
00135 mln_piter(I) p(input.domain());
00136 mln_niter(N) n(nbh, p);
00137 for_all(p)
00138 {
00139 if (!input(p) || dist_map(p) < static_cast<mln_value(D)>(0))
00140 continue;
00141
00142 unsigned nb_eq = 0;
00143 unsigned nb_lt = 0;
00144 for_all(n)
00145 if (input.domain().has(n)
00146
00147
00148
00149
00150 && dist_map(n) > static_cast<mln_value(D)>(0))
00151 {
00152 if (dist_map(n) == dist_map(p))
00153 ++nb_eq;
00154 else if (dist_map(n) < dist_map(p))
00155 ++nb_lt;
00156 }
00157
00158 if ((nb_lt + nb_eq) >= psi_threshold)
00159 is_crest(p) = true;
00160 }
00161
00162 trace::exiting("topo::skeleton::impl::generic::crest");
00163 return is_crest;
00164 }
00165
00166 }
00167
00168
00169
00170
00171 template <typename I, typename D, typename N>
00172 mln_concrete(I)
00173 crest_fastest_2d(const Image<I>& input_, const Image<D>& dist_map_,
00174 const Neighborhood<N>& nbh_, unsigned psi_threshold)
00175 {
00176 trace::entering("topo::skeleton::impl::crest_fastest_2d");
00177
00178 const I& input = exact(input_);
00179 const D& dist_map = exact(dist_map_);
00180 const N& nbh = exact(nbh_);
00181
00182 mlc_equal(mln_value(I), bool)::check();
00183 mln_precondition(input.is_valid());
00184 mln_precondition(dist_map.is_valid());
00185 mln_precondition(nbh.is_valid());
00186 mln_precondition(input.domain() == dist_map.domain());
00187
00188 extension::adjust(input, nbh);
00189 border::equalize(input, dist_map, input.border());
00190
00191 mln_concrete(I) is_crest;
00192 initialize(is_crest, input);
00193 data::fill(is_crest, false);
00194
00195
00196 mln_pixter(const I) p(input);
00197 util::array<int> dp = mln::offsets_wrt(input, nbh);
00198 unsigned n_nbhs = dp.nelements();
00199 for_all(p)
00200 {
00201 if (!p.val()
00202 || dist_map.element(p) < static_cast<mln_value(D)>(0))
00203 continue;
00204
00205 unsigned nb_eq = 0;
00206 unsigned nb_lt = 0;
00207 for (unsigned i = 0; i < n_nbhs; ++i)
00208 {
00209 unsigned n = p.offset() + dp[i];
00210 if (
00211
00212
00213
00214 dist_map.element(n) > static_cast<mln_value(D)>(0))
00215 {
00216 if (dist_map.element(n) == dist_map.element(p))
00217 ++nb_eq;
00218 else if (dist_map.element(n) < dist_map.element(p))
00219 ++nb_lt;
00220 }
00221
00222 if ((nb_lt + nb_eq) >= psi_threshold)
00223 is_crest.element(p) = true;
00224 }
00225
00226 }
00227
00228 trace::exiting("topo::skeleton::impl::crest_fastest_2d");
00229 return is_crest;
00230 }
00231
00232 }
00233
00234
00235
00236
00237 namespace internal
00238 {
00239
00240 template <typename I, typename D, typename N>
00241 mln_concrete(I)
00242 crest_dispatch_2d(mln::trait::image::value_storage::any,
00243 mln::trait::image::value_access::any,
00244 mln::trait::image::ext_domain::any,
00245 const Image<I>& input, const Image<D>& dist_map,
00246 const Neighborhood<N>& nbh, unsigned psi_threshold)
00247 {
00248 return skeleton::impl::generic::crest(input, dist_map,
00249 nbh, psi_threshold);
00250 }
00251
00252
00253 template <typename I, typename D, typename N>
00254 mln_concrete(I)
00255 crest_dispatch_2d(mln::trait::image::value_storage::one_block,
00256 mln::trait::image::value_access::direct,
00257 mln::trait::image::ext_domain::some,
00258 const Image<I>& input, const Image<D>& dist_map,
00259 const Neighborhood<N>& nbh, unsigned psi_threshold)
00260 {
00261 return skeleton::impl::crest_fastest_2d(input, dist_map,
00262 nbh, psi_threshold);
00263 }
00264
00265
00266 template <typename I, typename D, typename N>
00267 mln_concrete(I)
00268 crest_dispatch(const Image<I>& input, const Image<D>& dist_map,
00269 const Neighborhood<N>& nbh, unsigned psi_threshold)
00270 {
00271 unsigned dim = mln_site_(I)::dim;
00272
00273 if (dim == 2)
00274 return
00275 crest_dispatch_2d(mln_trait_image_value_storage(I)(),
00276 mln_trait_image_value_access(I)(),
00277 mln_trait_image_ext_domain(I)(),
00278 input, dist_map, nbh, psi_threshold);
00279
00280 return impl::generic::crest(input, dist_map, nbh, psi_threshold);
00281 }
00282
00283
00284 }
00285
00286
00287
00288
00289 template <typename I, typename D, typename N>
00290 mln_concrete(I)
00291 crest(const Image<I>& input, const Image<D>& dist_map,
00292 const Neighborhood<N>& nbh, unsigned psi_threshold)
00293 {
00294 trace::entering("topo::skeleton::crest");
00295
00296 mlc_equal(mln_value(I), bool)::check();
00297 mln_precondition(exact(input).is_valid());
00298 mln_precondition(exact(dist_map).is_valid());
00299 mln_precondition(exact(nbh).is_valid());
00300
00301 mln_concrete(I)
00302 output = internal::crest_dispatch(input, dist_map,
00303 nbh, psi_threshold);
00304
00305 trace::exiting("topo::skeleton::crest");
00306 return output;
00307 }
00308
00309
00310 template <typename I, typename D, typename N>
00311 mln_concrete(I)
00312 crest(const Image<I>& input, const Image<D>& dist_map,
00313 const Neighborhood<N>& nbh)
00314 {
00315 return crest(input, dist_map, nbh, 6);
00316 }
00317
00318 # endif // ! MLN_INCLUDE_ONLY
00319
00320
00321 }
00322
00323 }
00324
00325 }
00326
00327 #endif // ! MLN_TOPO_SKELETON_CREST_HH