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
00029 #ifndef OLENA_TOPO_DMAP_HXX
00030 # define OLENA_TOPO_DMAP_HXX
00031
00032 # include <mlc/array/2d.hh>
00033 # include <ntg/float.hh>
00034 # include <oln/arith/ops.hh>
00035
00036 namespace oln {
00037
00038 namespace topo {
00039
00040
00041
00042
00043
00044 template <class T>
00045 chamfer<T>::chamfer(const w_window2d<T>& fwd,
00046 const w_window2d<T>& bkd,
00047 float coef) :
00048 fwd(fwd),
00049 bkd(bkd),
00050 coef(coef)
00051 {}
00052
00053 template <class T>
00054 coord
00055 chamfer<T>::delta() const
00056 {
00057 coord d = fwd.delta();
00058 invariant(bkd.delta() == d);
00059 return d;
00060 }
00061
00062
00063
00064 template<int d10, int d11> inline
00065 const chamfer<int>&
00066 mk_chamfer_3x3(float coef)
00067 {
00068 static const w_window2d<int> w_win_fwd = ( mlc::ints_2d =
00069 d11, d10, d11, mlc::lbrk,
00070 d10, mlc::x(), 0, end );
00071 static const w_window2d<int> w_win_bkd = ( mlc::ints_2d =
00072 0, mlc::x(), d10, mlc::lbrk,
00073 d11, d10, d11, end );
00074 static const chamfer<int> ch_ = chamfer<int>(w_win_fwd, w_win_bkd, coef);
00075 return ch_;
00076 }
00077
00078 inline
00079 const chamfer<float>&
00080 mk_chamfer_3x3(float d10, float d11)
00081
00082 {
00083 static const w_window2d<float> w_win_fwd = ( mlc::floats_2d =
00084 d11, d10, d11, mlc::lbrk,
00085 d10, mlc::x(), 0.f, end );
00086 static const w_window2d<float> w_win_bkd = ( mlc::floats_2d =
00087 0.f, mlc::x(), d10, mlc::lbrk,
00088 d11, d10, d11, end );
00089 static const chamfer<float> ch_ =
00090 chamfer<float>(w_win_fwd, w_win_bkd, 1.f);
00091 return ch_;
00092 }
00093
00094 template<int d10, int d11, int d21> inline
00095 const chamfer<int>&
00096 mk_chamfer_5x5(float coef)
00097 {
00098 static const w_window2d<int> w_win_fwd = ( mlc::ints_2d =
00099 0, d21, 0, d21, 0, mlc::lbrk,
00100 d21, d11, d10, d11, d21,
00101 0, d10, mlc::x(), 0, 0, end );
00102 static const w_window2d<int> w_win_bkd = ( mlc::ints_2d =
00103 0, 0, mlc::x(), d10, 0, mlc::lbrk,
00104 d21, d11, d10, d11, d21,
00105 0, d21, 0, d21, 0, end );
00106 static const chamfer<int> ch_ = chamfer<int>(w_win_fwd, w_win_bkd, coef);
00107 return ch_;
00108 }
00109
00110 inline
00111 const chamfer<float>&
00112 mk_chamfer_5x5(float d10, float d11, float d21)
00113 {
00114 const float O = 0.f;
00115 static const w_window2d<float> w_win_fwd = ( mlc::floats_2d =
00116 O, d21, O, d21, O, mlc::lbrk,
00117 d21, d11, d10, d11, d21,
00118 O, d10, mlc::x(), O, O, end );
00119 static const w_window2d<float> w_win_bkd = ( mlc::floats_2d =
00120 O, O, mlc::x(), d10, O, mlc::lbrk,
00121 d21, d11, d10, d11, d21,
00122 O, d21, O, d21, O, end );
00123 static const chamfer<float> ch_ =
00124 chamfer<float>(w_win_fwd, w_win_bkd, 1.f);
00125 return ch_;
00126 }
00127
00128
00129
00130
00131
00132 # define oln_topo_chamfer2_(Name, I, J, D, E) \
00133 inline const chamfer<int>& Name##_##I##_##J() \
00134 { \
00135 static const chamfer<int> tmp = \
00136 mk_chamfer_##D##x##D< I, J >(E); \
00137 return tmp; \
00138 }
00139
00140 # define oln_topo_chamfer3_(Name, I, J, K, D, E) \
00141 inline const chamfer<int>& Name##_##I##_##J##_##K() \
00142 { \
00143 static const chamfer<int> tmp = \
00144 mk_chamfer_##D##x##D< I, J, K >(E); \
00145 return tmp; \
00146 }
00147
00148 oln_topo_chamfer2_(chamfer, 1, 1, 3, 0.9003)
00149 oln_topo_chamfer2_(chamfer, 1, 2, 3, 1.2732)
00150 oln_topo_chamfer2_(chamfer, 2, 3, 3, 2.1736)
00151 oln_topo_chamfer2_(chamfer, 5, 7, 3, 5.2474)
00152 oln_topo_chamfer2_(chamfer, 12, 17, 3, 12.6684)
00153
00154 inline const chamfer<int>&
00155 chessboard()
00156 {
00157 return chamfer_1_1();
00158 }
00159
00160 inline const chamfer<int>&
00161 cityblock()
00162 {
00163 return chamfer_1_2();
00164 }
00165
00166 oln_topo_chamfer3_(chamfer, 4, 6, 9, 5, 4.1203)
00167 oln_topo_chamfer3_(chamfer, 5, 7, 11, 5, 5.0206)
00168 oln_topo_chamfer3_(chamfer, 9, 13, 20, 5, 9.1409)
00169 oln_topo_chamfer3_(chamfer, 16, 23, 36, 5, 16.3351)
00170
00171 inline const chamfer<float>& best_set_3x3()
00172 { return mk_chamfer_3x3(0.9481, 1.3408); }
00173 inline const chamfer<float>& best_set_5x5()
00174 { return mk_chamfer_5x5(0.9801, 1.4060, 2.2044); }
00175
00176
00177 oln_topo_chamfer2_(mchamfer, 1, 1, 3, 0.8536)
00178 oln_topo_chamfer2_(mchamfer, 1, 2, 3, 1.2071)
00179 oln_topo_chamfer2_(mchamfer, 2, 3, 3, 2.1180)
00180 oln_topo_chamfer2_(mchamfer, 5, 7, 3, 5.1675)
00181 oln_topo_chamfer2_(mchamfer, 12, 17, 3, 12.5000)
00182
00183 inline const chamfer<int>& mchessboard() { return mchamfer_1_1(); }
00184 inline const chamfer<int>& mcityblock() { return mchamfer_1_2(); }
00185
00186 oln_topo_chamfer3_(mchamfer, 4, 6, 9, 5, 4.1213)
00187 oln_topo_chamfer3_(mchamfer, 5, 7, 11, 5, 5.0092)
00188 oln_topo_chamfer3_(mchamfer, 9, 13, 20, 5, 9.0819)
00189 oln_topo_chamfer3_(mchamfer, 17, 24, 38, 5, 17.2174)
00190
00191 inline const chamfer<float>& mbest_set_3x3() {
00192 const float coef = 1.0412;
00193 return mk_chamfer_3x3(1/coef, sqrt(2.f)/coef);
00194 }
00195 inline const chamfer<float>& mbest_set_5x5() {
00196 const float coef = 1.0137;
00197 return mk_chamfer_5x5(1/coef, sqrt(2.f)/coef, sqrt(5.f)/coef);
00198 }
00199
00200 # undef oln_topo_chamfer2_
00201 # undef oln_topo_chamfer3_
00202
00203 template <class T, class T2>
00204 dmap<T, T2>::dmap(const image2d_size& size,
00205 const chamfer<T2>& ch) :
00206 imap_(size),
00207 ch_(ch)
00208 {
00209
00210 }
00211
00212 template <class T, class T2>
00213 template <class V>
00214 void
00215 dmap<T, T2>::compute(const image2d<V>& input,
00216 float infty)
00217 {
00218 image2d<point_type> dummy(input.size());
00219 compute(input, dummy, infty);
00220 }
00221
00222 template <class T, class T2>
00223 template <class V>
00224 void dmap<T, T2>::compute(const image2d<V>& input,
00225 image2d<point_type>& nearest_point_map,
00226 float infty)
00227 {
00228 precondition(input.size() == imap_.size());
00229 if (infty == 0.f)
00230 {
00231 inFty_ = ntg_max_val(T);
00232 infTy_ = ntg_max_val(T);
00233 }
00234 else
00235 {
00236 inFty_ = infty;
00237 infTy_ = T(infty);
00238 }
00239
00240
00241 {
00242 typename image2d<V>::iter_type p(input);
00243 for (p = begin; p != end; ++p)
00244 if (input[p] != ntg_zero_val(V))
00245 {
00246 imap_[p] = T(0);
00247 nearest_point_map[p] = p;
00248 }
00249 else
00250 imap_[p] = infTy_;
00251 imap_.border_adapt_copy(ch_.delta());
00252 }
00253
00254
00255 {
00256 typename image2d<V>::fwd_iter_type p(input);
00257 for (p = begin; p != end; ++p)
00258 {
00259 if (imap_[p] == T(0))
00260 continue;
00261 T min = imap_[p];
00262 for (unsigned i = 0; i < ch_.fwd.card(); ++i)
00263 {
00264 point_type q = p + ch_.fwd.dp(i);
00265 if (imap_[q] == infTy_)
00266 continue;
00267 if (imap_[q] + ch_.fwd.w(i) < min)
00268 {
00269 nearest_point_map[p] = nearest_point_map[q];
00270 min = imap_[q] + ch_.fwd.w(i);
00271 }
00272 }
00273 imap_[p] = min;
00274 }
00275 }
00276
00277
00278 {
00279 typename image2d<V>::bkd_iter_type p(input);
00280 for_all(p)
00281 {
00282 if (imap_[p] == T(0))
00283 continue;
00284 T min = imap_[p];
00285 for (unsigned i = 0; i < ch_.bkd.card(); ++i)
00286 {
00287 point_type q = p + ch_.bkd.dp(i);
00288 if (imap_[q] == infTy_)
00289 continue;
00290 if (imap_[q] + ch_.bkd.w(i) < min)
00291 {
00292 nearest_point_map[p] = nearest_point_map[q];
00293 min = imap_[q] + ch_.bkd.w(i);
00294 }
00295 }
00296 imap_[p] = min;
00297 }
00298 }
00299 }
00300
00301 template <class T, class T2>
00302 const image2d<T>&
00303 dmap<T, T2>::imap() const
00304 {
00305 return imap_;
00306 }
00307
00308 template <class T, class T2>
00309 image2d<float>
00310 dmap<T, T2>::to_image() const
00311 {
00312
00313
00314
00315 image2d<float> output(imap_.size());
00316 typename image2d<float>::iter_type p(imap_);
00317 for_all(p)
00318 output[p] = (imap_[p] == infTy_ ?
00319 inFty_ :
00320 imap_[p] / ch_.coef);
00321 return output;
00322 }
00323
00324 template <class T, class T2>
00325 const T
00326 dmap<T, T2>::operator[](const point_type& p) const
00327 {
00328 return imap_[p] / ch_.coef;
00329 }
00330
00331 template <class T, class T2>
00332 const T
00333 dmap<T, T2>::operator()(coord row, coord col) const
00334 {
00335 return imap_(row, col) / ch_.coef;
00336 }
00337
00338 inline float
00339 euclidian_dist2(const point2d& p1, const point2d& p2)
00340 {
00341 float dr = p1.row() - p2.row();
00342 float dc = p1.col() - p2.col();
00343 return dr * dr + dc * dc;
00344 }
00345
00346
00347
00348 template <class I>
00349 image2d<float>
00350 exact_dmap(const abstract::image<I>& input)
00351 {
00352 image2d<float> output(input.size());
00353 image2d<float>::fwd_iter_type p(input);
00354 for_all(p)
00355 {
00356 if (input[p] == true)
00357 {
00358 output[p] = 0.f;
00359 continue;
00360 }
00361 image2d<float>::fwd_iter_type q(input);
00362 bool found = false;
00363 float d = 0.f;
00364 for_all(q)
00365 {
00366 if (input[q] == false || q == p)
00367 continue;
00368 if (! found)
00369 {
00370 d = euclidian_dist2(p, q);
00371 found = true;
00372 continue;
00373 }
00374 d = std::min(euclidian_dist2(p, q), d);
00375 }
00376 output[p] = sqrt(d);
00377 }
00378 return output;
00379 }
00380
00381 }
00382
00383 }
00384
00385 #endif // ! OLENA_TOPO_DMAP_HXX