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_CANVAS_LABELING_VIDEO_HH
00028 # define MLN_CANVAS_LABELING_VIDEO_HH
00029
00036
00037 # include <mln/core/concept/image.hh>
00038 # include <mln/data/fill.hh>
00039 # include <mln/literal/zero.hh>
00040 # include <mln/extension/adjust_fill.hh>
00041
00042 # include <mln/canvas/labeling/internal/tests.hh>
00043 # include <mln/canvas/labeling/internal/find_root_fastest.hh>
00044 # include <mln/canvas/labeling/generic.hh>
00045
00046 namespace mln
00047 {
00048
00049 namespace canvas
00050 {
00051
00052 namespace labeling
00053 {
00054
00055 template <typename I, typename N, typename L, typename F>
00056 mln_ch_value(I, L)
00057 video(const Image<I>& input, const Neighborhood<N>& nbh,
00058 L& nlabels, F& functor);
00059
00060
00061 # ifndef MLN_INCLUDE_ONLY
00062
00063
00064
00065
00066 namespace impl
00067 {
00068
00069 template <typename I, typename N, typename L, typename F>
00070 mln_ch_value(I, L)
00071 video_fastest(const Image<I>& input_,
00072 const Neighborhood<N>& nbh_,
00073 L& nlabels, F& f)
00074 {
00075 trace::entering("canvas::impl::video_fastest");
00076
00077
00078
00079 const I& input = exact(input_);
00080 const N& nbh = exact(nbh_);
00081
00082 extension::adjust(input, nbh);
00083
00084
00085 mln_ch_value(I, bool) deja_vu;
00086 mln_ch_value(I, unsigned) parent;
00087
00088
00089 mln_ch_value(I, L) output;
00090 bool status;
00091
00092
00093 {
00094 initialize(deja_vu, input);
00095 mln::data::fill(deja_vu, true);
00096 extension::fill(deja_vu, false);
00097
00098 initialize(parent, input);
00099
00100 initialize(output, input);
00101 mln::data::fill(output, L(literal::zero));
00102 nlabels = 0;
00103
00104 f.init_();
00105 }
00106
00107
00108 {
00109 util::array<int> dp = positive_offsets_wrt(input, nbh);
00110 const unsigned n_nbhs = dp.nelements();
00111
00112 mln_bkd_pixter(const I) px(input);
00113 for_all(px)
00114 {
00115 unsigned p = px.offset();
00116 if (! f.handles_(p))
00117 continue;
00118
00119
00120 parent.element(p) = p;
00121 f.init_attr_(p);
00122 for (unsigned i = 0; i < n_nbhs; ++i)
00123 {
00124 unsigned n = p + dp[i];
00125 if (deja_vu.element(n))
00126 {
00127 if (f.equiv_(n, p))
00128 {
00129
00130 unsigned r = internal::find_root_fastest(parent, n);
00131 if (r != p)
00132 {
00133 parent.element(r) = p;
00134 f.merge_attr_(r, p);
00135 }
00136 }
00137 else
00138 f.do_no_union_(n, p);
00139 }
00140 }
00141 }
00142 }
00143
00144
00145 {
00146 mln_fwd_pixter(const I) px(input);
00147 for_all(px)
00148 {
00149 unsigned p = px.offset();
00150 if (! f.handles_(p))
00151 continue;
00152 if (parent.element(p) == p)
00153 {
00154 if (f.labels_(p))
00155 {
00156 if (nlabels == mln_max(L))
00157 {
00158 status = false;
00159 trace::warning("labeling aborted! Too many labels for \
00160 this label type: nlabels > \
00161 max(label_type).");
00162 return output;
00163 }
00164 output.element(p) = ++nlabels;
00165 f.set_new_label_(p, nlabels);
00166 }
00167 }
00168 else
00169 {
00170 L lbl = output.element(parent.element(p));
00171 output.element(p) = lbl;
00172 f.set_label_(p, lbl);
00173 }
00174 }
00175 status = true;
00176 }
00177
00178 f.finalize();
00179 trace::exiting("canvas::impl::video_fastest");
00180 return output;
00181 }
00182
00183 }
00184
00185
00186
00187
00188
00189 namespace internal
00190 {
00191
00192 template <typename I, typename N, typename L, typename F>
00193 inline
00194 mln_ch_value(I, L)
00195 video_dispatch(metal::false_,
00196 const Image<I>& input,
00197 const Neighborhood<N>& nbh, L& nlabels,
00198 F& functor)
00199 {
00200 return impl::generic::labeling(input, nbh, nlabels,
00201 exact(input).domain(), functor);
00202 }
00203
00204 template <typename I, typename N, typename L, typename F>
00205 inline
00206 mln_ch_value(I, L)
00207 video_dispatch(metal::true_,
00208 const Image<I>& input,
00209 const Neighborhood<N>& nbh, L& nlabels,
00210 F& functor)
00211 {
00212 return impl::video_fastest(input, nbh, nlabels, functor);
00213 }
00214
00215 template <typename I, typename N, typename L, typename F>
00216 inline
00217 mln_ch_value(I, L)
00218 video_dispatch(const Image<I>& input,
00219 const Neighborhood<N>& nbh, L& nlabels,
00220 F& functor)
00221 {
00222 enum {
00223 test = mlc_equal(mln_trait_image_speed(I),
00224 trait::image::speed::fastest)::value
00225 &&
00226 mln_is_simple_neighborhood(N)::value
00227 };
00228 return video_dispatch(metal::bool_<test>(),
00229 input, nbh, nlabels,
00230 functor);
00231 }
00232
00233
00234 }
00235
00236
00237
00238
00239
00240
00241 template <typename I, typename N, typename L, typename F>
00242 inline
00243 mln_ch_value(I, L)
00244 video(const Image<I>& input, const Neighborhood<N>& nbh,
00245 L& nlabels, F& functor)
00246 {
00247 trace::entering("canvas::video");
00248
00249 internal::labeling_tests(input, nbh, nlabels, functor);
00250
00251 mln_ch_value(I, L) output;
00252 output = internal::video_dispatch(input, nbh, nlabels,
00253 functor);
00254
00255 trace::exiting("canvas::video");
00256 return output;
00257 }
00258
00259 # endif // ! MLN_INCLUDE_ONLY
00260
00261 }
00262
00263 }
00264
00265 }
00266
00267
00268 #endif // ! MLN_CANVAS_LABELING_VIDEO_HH