dmap.hxx

00001 // Copyright (C) 2001, 2002, 2003, 2004, 2005 EPITA Research and
00002 // Development Laboratory
00003 //
00004 // This file is part of the Olena Library.  This library is free
00005 // software; you can redistribute it and/or modify it under the terms
00006 // of the GNU General Public License version 2 as published by the
00007 // Free Software Foundation.
00008 //
00009 // This library is distributed in the hope that it will be useful,
00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012 // General Public License for more details.
00013 //
00014 // You should have received a copy of the GNU General Public License
00015 // along with this library; see the file COPYING.  If not, write to
00016 // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00017 // Boston, MA 02110-1301, USA.
00018 //
00019 // As a special exception, you may use this file as part of a free
00020 // software library without restriction.  Specifically, if other files
00021 // instantiate templates or use macros or inline functions from this
00022 // file, or you compile this file and link it with other files to
00023 // produce an executable, this file does not by itself cause the
00024 // resulting executable to be covered by the GNU General Public
00025 // License.  This exception does not however invalidate any other
00026 // reasons why the executable file might be covered by the GNU General
00027 // Public License.
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 //     using mlc::lbrk;
00041 //     using mlc::end;
00042 //     using mlc::x;
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     // mk_chamfer...
00063     // FIXME: this is highly not thread safe !
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 // FIXME: how to define float by parameters?
00079     const chamfer<float>&
00080     mk_chamfer_3x3(float d10, float d11)
00081       // FIXME: add (?)  , float coef = 1.f
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     // REF: B.J.H. Verwer, Local distances for distance transformations
00129     // in two and three dimensions, Pattern Recognition Letters 12 (1991) 671-682
00130 
00131     // unbiased minimal mean square error for integer local distances (Table 5)
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     // maximum absolute error for integer local distances (Table 2)
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       // FIXME: if T is float then precondition(ch.coef == 1.f)
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); // FIXME: use ceil if T is integer!
00238         }
00239 
00240       // init
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()); // FIXME: this is geodesic only!
00252       }
00253 
00254       // fwd
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_) // FIXME: || imap_[q] >= min
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       // bkd
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_) // FIXME: || imap_[q] >= min
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       // FIXME: if T is float, call invariant(ch_.coef == 1.f);
00313       // and then return imap();
00314       // otherwise:     return arith::div(imap_, ch_.coef);
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     // FIXME: why abstract::image!
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   } // end of namespace topo
00382 
00383 } // end of namespace oln
00384 
00385 #endif // ! OLENA_TOPO_DMAP_HXX

Generated on Tue Feb 20 20:18:49 2007 for Olena by  doxygen 1.5.1