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_WATERSHED_HXX
00029 # define OLENA_MORPHO_WATERSHED_HXX
00030
00031 # include <oln/config/system.hh>
00032 # include <ntg/all.hh>
00033 # include <oln/level/fill.hh>
00034 # include <queue>
00035 # include <map>
00036
00037 namespace oln {
00038 namespace morpho {
00039
00040
00041
00042 # define oln_morpho_declare_soille_watershed_consts_(DestValue) \
00043 const DestValue mask = ntg::cast::force<DestValue >(ntg_max_val(DestValue) - 2); \
00044 const DestValue wshed = ntg_max_val(DestValue); \
00045 const DestValue init = ntg::cast::force<DestValue >(ntg_max_val(DestValue) - 1); \
00046 const DestValue inqueue = ntg::cast::force<DestValue >(ntg_max_val(DestValue) - 3); \
00047 const DestValue maxlevel = ntg::cast::force<DestValue >(inqueue - 1)
00048
00049 namespace internal {
00050
00051 struct watershed_seg_point_handler_
00052 {
00053 template<class Fifo, class II, class IO, class N>
00054 static inline void
00055 process (Fifo& fifo, const II&, IO& im_o, const N& Ng)
00056 {
00057 typedef oln_value_type(IO) destvalue_type;
00058 oln_morpho_declare_soille_watershed_consts_(destvalue_type);
00059 (void) init;
00060
00061 oln_point_type(II) p = fifo.front();
00062 fifo.pop();
00063
00064 oln_iter_type(N) p_prime(Ng);
00065
00066 bool flag = false;
00067 for_all (p_prime)
00068 if (im_o.hold(p + p_prime))
00069 {
00070 if (im_o[p + p_prime] <= maxlevel)
00071 {
00072
00073 if (im_o[p] == inqueue
00074 || (im_o[p] == wshed && flag == true))
00075 im_o[p] = im_o[p + p_prime];
00076 else if (im_o[p] <= maxlevel
00077 && (im_o[p] != im_o[p + p_prime]))
00078 {
00079 im_o[p] = wshed;
00080 flag = false;
00081 }
00082 }
00083 else if (im_o[p + p_prime] == wshed)
00084 {
00085 if (im_o[p] == inqueue)
00086 {
00087 im_o[p] = wshed;
00088 flag = true;
00089 }
00090 }
00091 else if (im_o[p + p_prime] == mask)
00092 {
00093 im_o[p + p_prime] = inqueue;
00094 fifo.push(p + p_prime);
00095 }
00096 }
00097 }
00098 };
00099
00100 struct watershed_con_point_handler_
00101 {
00102 template<class Fifo, class II, class IO, class N>
00103 static inline void
00104 process (Fifo& fifo, const II& im_i, IO& im_o, const N& Ng)
00105 {
00106 typedef oln_value_type(IO) destvalue_type;
00107 oln_morpho_declare_soille_watershed_consts_(destvalue_type);
00108 (void) init; (void) wshed;
00109
00110 oln_point_type(II) p = fifo.front();
00111 fifo.pop();
00112
00113 oln_neighb_type(N) p_prime(Ng, p);
00114
00115 if (im_o[p] == inqueue)
00116 {
00117
00118 for_all(p_prime)
00119 if (im_o.hold(p_prime) && im_o[p_prime] <= maxlevel)
00120 {
00121 oln_point_type(II) l = p_prime;
00122
00123 for_all_remaining(p_prime)
00124 if (im_o.hold(p_prime)
00125 && im_o[p_prime] <= maxlevel
00126 && im_i[p_prime] < im_i[l])
00127 l = p_prime;
00128
00129 im_o[p] = im_o[l];
00130 break;
00131 }
00132 }
00133
00134
00135 for_all (p_prime)
00136 if (im_o.hold(p_prime) && im_o[p_prime] == mask)
00137 {
00138 im_o[p_prime] = inqueue;
00139 fifo.push(p_prime);
00140 }
00141 }
00142 };
00143
00148 template<class Point, class T> inline
00149 bool
00150 watershed_seg_sort_(const std::pair<Point, T>& p1,
00151 const std::pair<Point, T>& p2)
00152 {
00153 return p1.second < p2.second;
00154 }
00155
00159 template<class PointHandler, class DestValue, class I, class N>
00160 typename mute<I, DestValue>::ret
00161 soille_watershed_(const abstract::non_vectorial_image<I>& im_i,
00162 const abstract::neighborhood<N>& Ng)
00163 {
00164 oln_morpho_declare_soille_watershed_consts_(DestValue);
00165
00166
00167 typedef typename mute<I, DestValue>::ret result_type;
00168 result_type im_o(im_i.size());
00169 level::fill(im_o, init);
00170 std::queue<oln_point_type(I) > fifo;
00171 DestValue current_label = ntg_min_val(DestValue);
00172
00173
00174
00175 std::vector< std::pair<oln_point_type(I),oln_value_type(I)> >
00176 histo(im_i.npoints());
00177
00178 {
00179 oln_iter_type(I) p(im_i);
00180 unsigned int i = 0;
00181 for_all (p)
00182 histo[i++] = std::pair<oln_point_type(I),oln_value_type(I)>(p, im_i[p]);
00183
00184
00185
00186 sort(histo.begin(), histo.end(),
00187 watershed_seg_sort_<oln_point_type(I),oln_value_type(I)>);
00188 }
00189
00190 for (unsigned int i = 0; i < histo.size(); )
00191
00192 {
00193 unsigned int level_start = i;
00194
00195 oln_value_type(I) h = histo[i].second;
00196
00197 oln_point_type(I) p;
00198 while (i < histo.size())
00199 {
00200 p = histo[i].first;
00201 if (im_i[p] != h)
00202 break;
00203
00204 im_o[p] = mask;
00205 oln_iter_type(N) p_prime(Ng);
00206 bool flag_exist = false;
00207 for_all (p_prime)
00208 if (im_o.hold(p + p_prime))
00209 {
00210 if (im_o[p + p_prime] == wshed
00211 || im_o[p + p_prime] <= maxlevel)
00212 flag_exist = true;
00213 }
00214 if (flag_exist == true)
00215 {
00216 im_o[p] = inqueue;
00217 fifo.push(p);
00218 }
00219
00220 ++i;
00221 }
00222
00223
00224
00225 while (!fifo.empty())
00226 PointHandler::process (fifo, im_i, im_o, Ng);
00227
00228
00229
00230
00231
00232 unsigned int j = level_start;
00233 while (j < histo.size())
00234 {
00235 p = histo[j].first;
00236 if (im_i[p] != h)
00237 break;
00238
00239 if (im_o[p] == mask)
00240 {
00241 current_label += 1;
00242
00243
00244
00245 if (current_label > maxlevel)
00246 current_label = ntg_min_val(DestValue);
00247
00248 fifo.push(p);
00249 im_o[p] = current_label;
00250 while (!fifo.empty())
00251 {
00252 oln_point_type(I) p_prime = fifo.front();
00253 fifo.pop();
00254 oln_iter_type(N) p_pprime(Ng);
00255 for (p_pprime = begin; p_pprime != end; ++ p_pprime)
00256 if (im_o.hold(p_prime + p_pprime)
00257 && im_o[p_prime + p_pprime] == mask)
00258 {
00259 fifo.push(p_prime + p_pprime);
00260 im_o[p_prime + p_pprime] = current_label;
00261 }
00262 }
00263 }
00264 ++j;
00265 }
00266 }
00267 return im_o;
00268 }
00269
00270 }
00271
00272
00273
00274 template<class DestValue, class I, class N>
00275 typename mute<I, DestValue>::ret
00276 watershed_seg(const abstract::non_vectorial_image<I>& im_i,
00277 const abstract::neighborhood<N>& Ng)
00278 {
00279 return internal::soille_watershed_<
00280 internal::watershed_seg_point_handler_, DestValue> (im_i, Ng);
00281 }
00282
00283 template<class DestValue, class I, class N>
00284 typename mute<I, DestValue>::ret
00285 watershed_con(const abstract::non_vectorial_image<I>& im_i,
00286 const abstract::neighborhood<N>& Ng)
00287 {
00288 return internal::soille_watershed_<
00289 internal::watershed_con_point_handler_, DestValue> (im_i, Ng);
00290 }
00291
00292
00299 template <class T>
00300 struct cmp_queue_elt
00301 {
00302 bool
00303 operator()(const std::pair<oln_point_type(T), oln_value_type(T)>& l,
00304 const std::pair<oln_point_type(T), oln_value_type(T)>& r) const
00305 {
00306 return l.second > r.second;
00307 }
00308 };
00309
00310
00311 template<class I1, class I2, class N> inline
00312 oln_concrete_type(I2)&
00313 watershed_seg_or(const abstract::non_vectorial_image<I1>& In,
00314 abstract::non_vectorial_image<I2>& Labels,
00315 const abstract::neighborhood<N>& Ng)
00316 {
00317
00318 typedef oln_value_type(I2) value_type;
00319 const oln_value_type(I2) wshed = ntg_max_val(value_type);
00320 const oln_value_type(I2) unknown = ntg_min_val(value_type);
00321
00322 typedef std::pair<oln_point_type(I1), oln_value_type(I1)> queue_elt_type;
00323 std::priority_queue< queue_elt_type, std::vector< queue_elt_type >,
00324 cmp_queue_elt<I1> > PQ;
00325
00326
00327
00328 {
00329 oln_iter_type(I2) p(Labels);
00330 oln_neighb_type(N) p_prime(Ng, p);
00331 for_all(p)
00332 if (Labels[p] != unknown)
00333 for_all (p_prime)
00334 if (Labels.hold(p_prime) && Labels[p_prime] == unknown)
00335 {
00336 PQ.push(queue_elt_type(p, In[p]));
00337 break;
00338 }
00339 }
00340
00341
00342
00343 oln_point_type(I1) p;
00344 oln_neighb_type(N) p_prime(Ng, p);
00345 oln_neighb_type(N) p_second(Ng, p_prime);
00346 while (! PQ.empty())
00347 {
00348
00349 p = PQ.top().first;
00350 PQ.pop();
00351
00352 for_all (p_prime) if (Labels.hold(p_prime))
00353 {
00354
00355 if (Labels[p_prime] == unknown)
00356 {
00357
00358
00359
00360
00361
00362
00363
00364
00365 bool exists = false;
00366 for_all (p_second)
00367
00368
00369
00370
00371
00372
00373 if (Labels.hold(p_second)
00374 && Labels[p_second] != unknown
00375 && Labels[p_second] != wshed
00376 && Labels[p_second] != Labels[p])
00377 {
00378 exists = true;
00379 break;
00380 }
00381 if (exists)
00382 Labels[p_prime] = wshed;
00383 else
00384 {
00385 Labels[p_prime] = Labels[p];
00386 PQ.push(queue_elt_type(p_prime, In[p_prime]));
00387 }
00388 }
00389 }
00390 }
00391 return Labels.exact();
00392 }
00393
00394 }
00395 }
00396
00397
00398 #endif // OLENA_MORPHO_WATERSHED_HXX