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 }
00166 }
00167 else
00168 output.element(p) = output.element(parent.element(p));
00169 }
00170 status = true;
00171 }
00172
00173 trace::exiting("canvas::impl::video_fastest");
00174 return output;
00175 }
00176
00177 }
00178
00179
00180
00181
00182
00183 namespace internal
00184 {
00185
00186 template <typename I, typename N, typename L, typename F>
00187 inline
00188 mln_ch_value(I, L)
00189 video_dispatch(metal::false_,
00190 const Image<I>& input,
00191 const Neighborhood<N>& nbh, L& nlabels,
00192 F& functor)
00193 {
00194 return impl::generic::labeling(input, nbh, nlabels,
00195 exact(input).domain(), functor);
00196 }
00197
00198 template <typename I, typename N, typename L, typename F>
00199 inline
00200 mln_ch_value(I, L)
00201 video_dispatch(metal::true_,
00202 const Image<I>& input,
00203 const Neighborhood<N>& nbh, L& nlabels,
00204 F& functor)
00205 {
00206 return impl::video_fastest(input, nbh, nlabels, functor);
00207 }
00208
00209 template <typename I, typename N, typename L, typename F>
00210 inline
00211 mln_ch_value(I, L)
00212 video_dispatch(const Image<I>& input,
00213 const Neighborhood<N>& nbh, L& nlabels,
00214 F& functor)
00215 {
00216 enum {
00217 test = mlc_equal(mln_trait_image_speed(I),
00218 trait::image::speed::fastest)::value
00219 &&
00220 mln_is_simple_neighborhood(N)::value
00221 };
00222 return video_dispatch(metal::bool_<test>(),
00223 input, nbh, nlabels,
00224 functor);
00225 }
00226
00227
00228 }
00229
00230
00231
00232
00233
00234
00235 template <typename I, typename N, typename L, typename F>
00236 inline
00237 mln_ch_value(I, L)
00238 video(const Image<I>& input, const Neighborhood<N>& nbh,
00239 L& nlabels, F& functor)
00240 {
00241 trace::entering("canvas::video");
00242
00243 internal::labeling_tests(input, nbh, nlabels, functor);
00244
00245 mln_ch_value(I, L) output;
00246 output = internal::video_dispatch(input, nbh, nlabels,
00247 functor);
00248
00249 trace::exiting("canvas::video");
00250 return output;
00251 }
00252
00253 # endif // ! MLN_INCLUDE_ONLY
00254
00255 }
00256
00257 }
00258
00259 }
00260
00261
00262 #endif // ! MLN_CANVAS_LABELING_VIDEO_HH