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
00031
00032 #include <mln/core/image/image2d.hh>
00033 #include <mln/core/alias/neighb2d.hh>
00034 #include <mln/value/int_u8.hh>
00035 #include <mln/io/pgm/load.hh>
00036
00037 #include <mln/labeling/level.hh>
00038 #include <mln/util/timer.hh>
00039
00040
00041 namespace mln
00042 {
00043
00044
00045 namespace old_canvas
00046 {
00047
00048 template <typename F>
00049 struct labeling
00050 {
00051
00052 F& f;
00053
00054 typedef typename F::I I;
00055 typedef typename F::N N;
00056 typedef typename F::L L;
00057 typedef typename F::S S;
00058
00059
00060 typedef mln_psite(I) psite;
00061
00062
00063 mln_ch_value(I, bool) deja_vu;
00064 mln_ch_value(I, psite) parent;
00065
00066
00067 mln_ch_value(I, L) output;
00068 L nlabels;
00069 bool status;
00070
00071
00072 labeling(F& f);
00073
00074 void init();
00075
00076 void pass_1();
00077
00078 void pass_2();
00079
00080
00081
00082
00083 void make_set(const psite& p);
00084
00085 bool is_root(const psite& p) const;
00086
00087 psite find_root(const psite& x);
00088
00089 void do_union(const psite& n, const psite& p);
00090
00091 };
00092
00093
00094 template <typename F>
00095 labeling<F>::labeling(F& f)
00096 : f(f)
00097 {
00098 trace::entering("canvas::labeling");
00099
00100 init();
00101 f.init();
00102 pass_1();
00103 pass_2();
00104
00105 trace::exiting("canvas::labeling");
00106 }
00107
00108 template <typename F>
00109 void
00110 labeling<F>::init()
00111 {
00112 initialize(deja_vu, f.input);
00113 mln::data::fill(deja_vu, false);
00114 initialize(parent, f.input);
00115 initialize(output, f.input);
00116 mln::data::fill(output, L(literal::zero));
00117 nlabels = 0;
00118 }
00119
00120 template <typename F>
00121 void
00122 labeling<F>::pass_1()
00123 {
00124 mln_fwd_piter(S) p(f.s);
00125 mln_niter(N) n(f.nbh, p);
00126 for_all(p) if (f.handles(p))
00127 {
00128 make_set(p);
00129 for_all(n)
00130 if (f.input.domain().has(n) && deja_vu(n))
00131 {
00132 if (f.equiv(n, p))
00133 do_union(n, p);
00134 else
00135 f.do_no_union(n, p);
00136 }
00137 deja_vu(p) = true;
00138 }
00139 }
00140
00141 template <typename F>
00142 void
00143 labeling<F>::pass_2()
00144 {
00145 mln_bkd_piter(S) p(f.s);
00146 for_all(p) if (f.handles(p))
00147 {
00148 if (is_root(p))
00149 {
00150 if (f.labels(p))
00151 {
00152 if (nlabels == mln_max(L))
00153 {
00154 status = false;
00155 return;
00156 }
00157 output(p) = ++nlabels;
00158 }
00159 }
00160 else
00161 output(p) = output(parent(p));
00162 }
00163 status = true;
00164 }
00165
00166 template <typename F>
00167 void
00168 labeling<F>::make_set(const psite& p)
00169 {
00170 parent(p) = p;
00171 f.init_attr(p);
00172 }
00173
00174 template <typename F>
00175 bool
00176 labeling<F>::is_root(const psite& p) const
00177 {
00178 return parent(p) == p;
00179 }
00180
00181 template <typename F>
00182 typename labeling<F>::psite
00183 labeling<F>::find_root(const psite& x)
00184 {
00185 if (parent(x) == x)
00186 return x;
00187 else
00188 return parent(x) = find_root(parent(x));
00189 }
00190
00191 template <typename F>
00192 void
00193 labeling<F>::do_union(const psite& n, const psite& p)
00194 {
00195 psite r = find_root(n);
00196 if (r != p)
00197 {
00198 parent(r) = p;
00199 f.merge_attr(r, p);
00200 }
00201 }
00202
00203
00204 }
00205
00206
00207
00208 namespace old_labeling
00209 {
00210
00211
00212 template <typename I_, typename N_, typename L_>
00213 struct level_functor
00214 {
00215 typedef mln_psite(I_) P;
00216
00217
00218
00219 typedef I_ I;
00220 typedef N_ N;
00221 typedef L_ L;
00222 typedef mln_pset(I) S;
00223
00224 const I& input;
00225 const N& nbh;
00226 const S& s;
00227
00228 bool handles(const P& p) const { return input(p) == val; }
00229 bool equiv(const P& n, const P&) const { return input(n) == val; }
00230
00231 void init() {}
00232 bool labels(const P&) const { return true; }
00233 void do_no_union(const P&, const P&) {}
00234 void init_attr(const P&) {}
00235 void merge_attr(const P&, const P&) {}
00236
00237
00238
00239 const mln_value(I_)& val;
00240
00241 level_functor(const I& input, const mln_value(I)& val, const N& nbh)
00242 : input(input),
00243 nbh(nbh),
00244 s(input.domain()),
00245 val(val)
00246 {}
00247 };
00248
00249
00250
00251 template <typename I, typename N, typename L>
00252 mln_ch_value(I, L)
00253 level(const Image<I>& input, const mln_value(I)& val, const Neighborhood<N>& nbh,
00254 L& nlabels)
00255 {
00256 trace::entering("labeling::value");
00257
00258 typedef level_functor<I,N,L> F;
00259 F f(exact(input), val, exact(nbh));
00260 old_canvas::labeling<F> run(f);
00261
00262 nlabels = run.nlabels;
00263
00264 trace::exiting("labeling::value");
00265 return run.output;
00266 }
00267
00268 }
00269
00270 }
00271
00272
00273
00274
00275 int main()
00276 {
00277 using namespace mln;
00278 using value::int_u8;
00279
00280 image2d<int_u8> lena;
00281 io::pgm::load(lena, "../../img/lena.pgm");
00282
00283 {
00284 util::timer t;
00285 t.start();
00286 unsigned n;
00287 for (unsigned l = 0; l <= 255; ++l)
00288 old_labeling::value(lena, l, c4(), n);
00289 std::cout << "canvas as class: " << t.read() << std::endl;
00290 }
00291
00292 {
00293 util::timer t;
00294 t.start();
00295 unsigned n;
00296 for (unsigned l = 0; l <= 255; ++l)
00297 labeling::impl::generic::data(lena, l, c4(), n);
00298 std::cout << "canvas as proc.: " << t.read() << std::endl;
00299 }
00300
00301 }