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_BLOBS_HH
00028 # define MLN_CANVAS_LABELING_BLOBS_HH
00029
00034
00035 # include <mln/core/concept/image.hh>
00036 # include <mln/core/concept/neighborhood.hh>
00037 # include <mln/data/fill.hh>
00038 # include <mln/core/site_set/p_queue_fast.hh>
00039
00040 # include <mln/extension/fill.hh>
00041
00042 # include <mln/util/pix.hh>
00043
00044 namespace mln
00045 {
00046
00047 namespace canvas
00048 {
00049
00050 namespace labeling
00051 {
00052
00069 template <typename I, typename N, typename L, typename F>
00070 mln_ch_value(I, L)
00071 blobs(const Image<I>& input_, const Neighborhood<N>& nbh_,
00072 L& nlabels, F& functor);
00073
00074
00075
00076 # ifndef MLN_INCLUDE_ONLY
00077
00078
00079
00080
00081 namespace impl
00082 {
00083
00084
00085
00086 namespace generic
00087 {
00088
00089 template <typename I, typename N, typename L, typename F>
00090 mln_ch_value(I, L)
00091 blobs(const Image<I>& input_, const N& nbh, L& nlabels, F& functor)
00092 {
00093 const I& input = exact(input_);
00094
00095 typedef mln_psite(I) P;
00096
00097 P cur;
00098 mln_niter(N) n(nbh, cur);
00099 p_queue_fast<P> qu;
00100 const L zero = literal::zero;
00101
00102
00103 nlabels = literal::zero;
00104 typedef mln_ch_value(I, L) out_t;
00105 out_t output;
00106 initialize(output, input);
00107 data::fill(output, zero);
00108
00109 extension::fill(input, false);
00110
00111 functor.init();
00112
00113
00114 mln_piter(I) p(input.domain());
00115 for_all(p)
00116 if (input(p) && output(p) == zero)
00117 {
00118
00119 if (nlabels == mln_max(L))
00120 {
00121 trace::warning("labeling aborted! Too many labels \
00122 for this label type: nlabels > max(label_type).");
00123
00124 return output;
00125 }
00126 ++nlabels;
00127 functor.new_label(nlabels);
00128 mln_invariant(qu.is_empty());
00129 qu.push(p);
00130 output(p) = nlabels;
00131 functor.process_p(p);
00132
00133 do
00134 {
00135 cur = qu.front();
00136 qu.pop();
00137 for_all(n) if (input.has(n))
00138 if (input(n) && output(n) == zero)
00139 {
00140 mln_invariant(! qu.compute_has(n));
00141 qu.push(n);
00142 output(n) = nlabels;
00143 functor.process_n(n);
00144
00145 }
00146 }
00147 while (! qu.is_empty());
00148 }
00149
00150 functor.finalize();
00151
00152 return output;
00153 }
00154
00155 }
00156
00157
00158
00159 }
00160
00161
00162
00163
00164 template <typename I, typename N, typename L, typename F>
00165 inline
00166 mln_ch_value(I, L)
00167 blobs(const Image<I>& input_, const Neighborhood<N>& nbh_,
00168 L& nlabels, F& functor)
00169 {
00170 trace::entering("labeling::blobs");
00171 mlc_equal(mln_trait_image_kind(I),
00172 mln::trait::image::kind::binary)::check();
00173 const I& input = exact(input_);
00174 const N& nbh = exact(nbh_);
00175 mln_precondition(input.is_valid());
00176
00177
00178 mln_ch_value(I, L)
00179 output = impl::generic::blobs(input, nbh, nlabels, functor);
00180
00181 trace::exiting("labeling::blobs");
00182 return output;
00183 }
00184
00185
00186 # endif // ! MLN_INCLUDE_ONLY
00187
00188 }
00189
00190 }
00191
00192 }
00193
00194
00195 #endif // ! MLN_CANVAS_LABELING_BLOBS_HH