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_MORPHO_SKELETON_CONSTRAINED_HH
00028 # define MLN_MORPHO_SKELETON_CONSTRAINED_HH
00029
00036
00037 # include <mln/core/concept/image.hh>
00038 # include <mln/core/concept/neighborhood.hh>
00039 # include <mln/core/site_set/p_queue_fast.hh>
00040 # include <mln/core/site_set/p_priority.hh>
00041 # include <mln/extension/adjust_duplicate.hh>
00042 # include <mln/extension/adjust_fill.hh>
00043 # include <mln/data/fill.hh>
00044
00045 # include <mln/util/timer.hh>
00046
00047 namespace mln
00048 {
00049
00050 namespace morpho
00051 {
00052
00053 template <typename I,
00054 typename N, typename F,
00055 typename K, typename R>
00056 mln_ch_value(I, bool)
00057 skeleton_constrained(const Image<I>& input,
00058 const Neighborhood<N>& nbh, const F& is_simple,
00059 const Image<K>& constraint, const Image<R>& priority);
00060
00061
00062
00063 # ifndef MLN_INCLUDE_ONLY
00064
00065
00066 namespace impl
00067 {
00068
00069 namespace generic
00070 {
00071
00072 template <typename I,
00073 typename N, typename F,
00074 typename K, typename R>
00075 inline
00076 mln_ch_value(I, bool)
00077 skeleton_constrained(const Image<I>& input_,
00078 const Neighborhood<N>& nbh_, const F& is_simple,
00079 const Image<K>& constraint_, const Image<R>& priority_)
00080 {
00081 trace::entering("morpho::skeleton_constrained");
00082
00083 const I& input = exact(input_);
00084 const N& nbh = exact(nbh_);
00085 const K& constraint = exact(constraint_);
00086 const R& priority = exact(priority_);
00087
00088 mln_precondition(input.is_valid());
00089 mln_precondition(nbh.is_valid());
00090 mln_precondition(constraint.is_valid());
00091 mln_precondition(priority.is_valid());
00092
00093 typedef mln_value(I) V;
00094 mlc_is(V, bool)::check();
00095
00096 extension::adjust_duplicate(input, nbh);
00097 extension::adjust_duplicate(constraint, nbh);
00098 extension::adjust_duplicate(priority, nbh);
00099
00100
00101
00102 typedef mln_psite(I) P;
00103 typedef p_queue_fast<P> Q;
00104 p_priority<mln_value(R), Q> q;
00105
00106 mln_concrete(I) output;
00107
00108
00109 {
00110 output = duplicate(input);
00111 extension::adjust_duplicate(output, nbh);
00112
00113 mln_piter(I) p(input.domain());
00114 for_all(p)
00115 if (input(p) == false &&
00116 is_simple.check(input, p))
00117
00118 {
00119 q.push(priority(p), p);
00120 }
00121 }
00122
00123
00124 {
00125 P p;
00126
00127 mln_niter(N) n(nbh, p);
00128 while (! q.is_empty())
00129 {
00130 p = q.pop_front();
00131 for_all(n)
00132 if (output.has(n) &&
00133 output(n) == true &&
00134 constraint(n) == false &&
00135 is_simple.check(output, n))
00136 {
00137 output(n) = false;
00138 q.push(priority(n), n);
00139 }
00140 }
00141 }
00142
00143 trace::exiting("morpho::skeleton_constrained");
00144 return output;
00145 }
00146
00147 }
00148
00149
00150 template <typename I,
00151 typename N, typename F,
00152 typename K, typename R>
00153 inline
00154 mln_ch_value(I, bool)
00155 skeleton_constrained_fast(const Image<I>& input_,
00156 const Neighborhood<N>& nbh_,
00157 const F& is_simple,
00158 const Image<K>& constraint_,
00159 const Image<R>& priority_)
00160 {
00161 trace::entering("morpho::skeleton_constrained_fast");
00162
00163 const I& input = exact(input_);
00164 const N& nbh = exact(nbh_);
00165 const K& constraint = exact(constraint_);
00166 const R& priority = exact(priority_);
00167
00168 mln_precondition(input.is_valid());
00169 mln_precondition(nbh.is_valid());
00170 mln_precondition(constraint.is_valid());
00171 mln_precondition(priority.is_valid());
00172
00173 typedef mln_value(I) V;
00174 mlc_is(V, bool)::check();
00175
00176
00177
00178
00179
00180
00181 extension::adjust_fill(input, nbh, false);
00182 extension::adjust_fill(constraint, nbh, false);
00183
00184
00185
00186 typedef p_queue_fast<unsigned> Q;
00187 p_priority<mln_value(R), Q> q;
00188
00189 mln_concrete(I) output;
00190
00191
00192 {
00193 output = duplicate(input);
00194 extension::adjust_fill(output, nbh, false);
00195
00196 mln_pixter(const I) p_in(input);
00197 for_all(p_in)
00198 if (p_in.val() == false &&
00199 is_simple.check__(input, p_in))
00200
00201 {
00202 q.push(priority.element(p_in.offset()), p_in);
00203 }
00204 }
00205
00206
00207 {
00208 util::array<int> dp = offsets_wrt(input, nbh.foreground());
00209 const unsigned n_nbhs = dp.nelements();
00210 while (! q.is_empty())
00211 {
00212 unsigned p = q.pop_front();
00213
00214 for (unsigned i = 0; i < n_nbhs; ++i)
00215 {
00216 unsigned n = p + dp[i];
00217
00218 if (output.element(n) == true &&
00219 constraint.element(n) == false &&
00220 is_simple.check__(output, n))
00221 {
00222 output.element(n) = false;
00223 q.push(priority.element(n), n);
00224 }
00225 }
00226 }
00227 }
00228
00229 trace::exiting("morpho::skeleton_constrained_fast");
00230 return output;
00231 }
00232
00233
00234 }
00235
00236
00237 namespace internal
00238 {
00239
00240 template <typename I,
00241 typename N, typename F,
00242 typename K, typename R>
00243 inline
00244 mln_ch_value(I, bool)
00245 skeleton_constrained_dispatch(
00246 mln::trait::image::value_access::any,
00247 mln::trait::image::value_storage::any,
00248 const Image<I>& input,
00249 const Neighborhood<N>& nbh,
00250 const F& is_simple,
00251 const Image<K>& constraint,
00252 const Image<R>& priority)
00253 {
00254 return impl::generic::skeleton_constrained(input, nbh,
00255 is_simple,
00256 constraint,
00257 priority);
00258 }
00259
00260 template <typename I,
00261 typename N, typename F,
00262 typename K, typename R>
00263 inline
00264 mln_ch_value(I, bool)
00265 skeleton_constrained_dispatch(
00266 mln::trait::image::value_access::direct,
00267 mln::trait::image::value_storage::one_block,
00268 const Image<I>& input,
00269 const Neighborhood<N>& nbh,
00270 const F& is_simple,
00271 const Image<K>& constraint,
00272 const Image<R>& priority)
00273 {
00274 return impl::skeleton_constrained_fast(input, nbh,
00275 is_simple,
00276 constraint,
00277 priority);
00278 }
00279
00280
00281 }
00282
00283
00284 template <typename I,
00285 typename N, typename F,
00286 typename K, typename R>
00287 inline
00288 mln_ch_value(I, bool)
00289 skeleton_constrained(const Image<I>& input,
00290 const Neighborhood<N>& nbh, const F& is_simple,
00291 const Image<K>& constraint, const Image<R>& priority)
00292 {
00293 trace::entering("morpho::skeleton_constrained");
00294
00295 mln_ch_value(I, bool)
00296 output = internal::skeleton_constrained_dispatch(
00297 mln_trait_image_value_access(I)(),
00298 mln_trait_image_value_storage(I)(),
00299 input, nbh, is_simple, constraint, priority);
00300
00301 trace::exiting("morpho::skeleton_constrained");
00302 return output;
00303 }
00304
00305 # endif // ! MLN_INCLUDE_ONLY
00306
00307 }
00308
00309 }
00310
00311
00312 #endif // ! MLN_MORPHO_SKELETON_CONSTRAINED_HH