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