URL:
https://svn.lrde.epita.fr/svn/oln/trunk/milena
ChangeLog:
2007-09-12 Simon Nivault <simon.nivault(a)lrde.epita.fr>
add sym for weighted windows and beginning of dmap feature
* mln/geom/sym.hh: Update (geom::sym).
* sandbox/nivault/dmap.hh: New.
* sandbox/nivault/dmap.hxx: New.
---
mln/geom/sym.hh | 13 +
sandbox/nivault/dmap.hh | 576 +++++++++++++++++++++++++++++++++++++++++++++++
sandbox/nivault/dmap.hxx | 372 ++++++++++++++++++++++++++++++
3 files changed, 961 insertions(+)
Index: trunk/milena/mln/geom/sym.hh
===================================================================
--- trunk/milena/mln/geom/sym.hh (revision 1105)
+++ trunk/milena/mln/geom/sym.hh (revision 1106)
@@ -34,6 +34,7 @@
*/
# include <mln/core/concept/window.hh>
+# include <mln/core/concept/w_window.hh>
@@ -48,6 +49,11 @@
template <typename W>
W sym(const Window<W>& win);
+ /*! \brief Give the symmetrical weighted window of \p w_win.
+ */
+ template <typename W>
+ W sym(const Weighted_Window<W>& w_win);
+
# ifndef MLN_INCLUDE_ONLY
@@ -58,6 +64,13 @@
return tmp.sym();
}
+ template <typename W>
+ W sym(const Weighted_Window<W>& w_win)
+ {
+ W tmp = exact(win);
+ return tmp.sym();
+ }
+
# endif // ! MLN_INCLUDE_ONLY
} // end of namespace mln::geom
Index: trunk/milena/sandbox/nivault/dmap.hh
===================================================================
--- trunk/milena/sandbox/nivault/dmap.hh (revision 0)
+++ trunk/milena/sandbox/nivault/dmap.hh (revision 1106)
@@ -0,0 +1,576 @@
+// Copyright (C) 2001, 2002, 2003, 2004 EPITA Research and Development Laboratory
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
+// MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+#ifndef MLN_TOPO_DMAP_HH
+# define MLN_TOPO_DMAP_HH
+
+// include <ntg/bin.hh>
+// include <mln/basics2d.hh>
+# include <mln/core/w_window2d.hh>
+
+// \todo FIXME: math.h should be included by ntg/config/system.hh
+// include <math.h>
+// include <utility>
+
+/*! \file milenq/mln/topo/dmap.hh
+**
+** REF: B.J.H. Verwer, Local distances for distance transformations
+** in two and three dimensions, Pattern Recognition Letters 12 (1991) 671-682
+*/
+
+namespace oln {
+
+ /// \brief Topological algorithms.
+ namespace topo {
+ /*! Chamfer mask.
+ **
+ ** The Chamfer mask is a weighted masks that provides an approximation
+ ** of the real Euclidean distance in the discrete space.
+ */
+ template<class T>
+ struct chamfer
+ {
+ chamfer(const w_window2d<T>& win,
+ float coef);
+
+ coord
+ delta() const;
+
+ const w_window2d<T> win;
+ const float coef;
+ };
+
+ /*! Produce a chamfer mask 3x3
+ **
+ ** \todo FIXME: This highly not thread safe !
+ **
+ ** \verbatim
+ ** Example of oln::topo::mk_chamfer_3x3<1,2>(3) w;
+ ** w.delta(): 1
+ ** w.coef: 3
+ ** w.win:
+ ** 2 1 2
+ ** 1 . .
+ ** . . .
+ ** \endverbatim
+ */
+ template<int d10, int d11> inline
+ const chamfer<int>&
+ mk_chamfer_3x3(float coef = 1.f);
+
+ /*! Produce a chamfer mask 3x3
+ **
+ ** \todo FIXME: This highly not thread safe !
+ **
+ ** \verbatim
+ ** Example of oln::topo::mk_chamfer_3x3(1.5, 2.5) w;
+ ** w.delta(): 1
+ ** w.coef: 1
+ ** w.win:
+ ** 2.5 1.5 2.5
+ ** 1.5 . .
+ ** . . .
+ ** \endverbatim
+ */
+ inline
+ const chamfer<float>&
+ mk_chamfer_3x3(float d10, float d11);
+
+ /*! Chamfer 5x5
+ **
+ ** \verbatim
+ ** Example of oln::topo::mk_chamfer_5x5<1, 2, 3>(4) w;
+ ** w.delta(): 2
+ ** w.coef: 4
+ ** w.win:
+ ** . 3 . 3 .
+ ** 3 2 1 2 3
+ ** . 1 . . .
+ ** . . . . .
+ ** . . . . .
+ ** \endverbatim
+ */
+ template<int d10, int d11, int d21> inline
+ const chamfer<int>&
+ mk_chamfer_5x5(float coef = 1.f);
+
+ /*! Chamfer 5x5 using float
+ **
+ ** \see mk_chamfer_5x5
+ */
+ inline
+ const chamfer<float>&
+ mk_chamfer_5x5(float d10, float d11, float d21);
+
+ /*! Chamfer_1_1
+ **
+ ** \verbatim
+ ** Example of oln::topo::chamfer_1_1() w;
+ ** w.delta(): 1
+ ** w.coef: 0.9003
+ ** w.win:
+ ** 1 1 1
+ ** 1 . .
+ ** . . .
+ ** \endverbatim
+ */
+ inline const chamfer<int>& chamfer_1_1();
+
+ /*! Chamfer_1_2
+ **
+ ** \verbatim
+ ** Example of oln::topo::chamfer_1_2() w;
+ ** w.delta(): 1
+ ** w.coef: 1.2732
+ ** w.win:
+ ** 2 1 2
+ ** 1 . .
+ ** . . .
+ ** \endverbatim
+ */
+ inline const chamfer<int>& chamfer_1_2();
+ /*! Chamfer_2_3
+ **
+ ** \verbatim
+ ** Example of oln::topo::chamfer_2_3() w;
+ ** w.delta(): 1
+ ** w.coef: 2.1736
+ ** w.win:
+ ** 3 2 3
+ ** 2 . .
+ ** . . .
+ ** \endverbatim
+ */
+ inline const chamfer<int>& chamfer_2_3();
+ /*! Chamfer_5_7
+ **
+ ** \verbatim
+ ** Example of oln::topo::chamfer_5_7() w;
+ ** w.delta(): 1
+ ** w.coef: 5.2474
+ ** w.win:
+ ** 7 5 7
+ ** 5 . .
+ ** . . .
+ ** \endverbatim
+ */
+ inline const chamfer<int>& chamfer_5_7();
+ /*! Chamfer_12_17
+ **
+ ** \verbatim
+ ** Example of oln::topo::chamfer_12_17() w;
+ ** w.delta(): 1
+ ** w.coef: 12.6684
+ ** w.win:
+ ** 17 12 17
+ ** 12 . .
+ ** . . .
+ ** \endverbatim
+ */
+ inline const chamfer<int>& chamfer_12_17();
+ /*! Chessboard
+ **
+ ** \verbatim
+ ** Example of oln::topo::chessboard() w;
+ ** w.delta(): 1
+ ** w.coef: 0.9003
+ ** w.win:
+ ** 1 1 1
+ ** 1 . .
+ ** . . .
+ ** \endverbatim
+ */
+ inline const chamfer<int>& chessboard();
+ /*! Cityblock
+ **
+ ** \verbatim
+ ** Example of oln::topo::cityblock() w;
+ ** w.delta(): 1
+ ** w.coef: 1.2732
+ ** w.win:
+ ** 2 1 2
+ ** 1 . .
+ ** . . .
+ ** \endverbatim
+ */
+ inline const chamfer<int>& cityblock();
+ /*! Chamfer_4_6_9
+ **
+ ** \verbatim
+ ** Example of oln::topo::chamfer_4_6_9() w;
+ ** w.delta(): 2
+ ** w.coef: 4.1203
+ ** w.win:
+ ** . 9 . 9 .
+ ** 9 6 4 6 9
+ ** . 4 . . .
+ ** . . . . .
+ ** . . . . .
+ ** \endverbatim
+ */
+ inline const chamfer<int>& chamfer_4_6_9();
+ /*! Chamfer_5_7_11
+ **
+ ** \verbatim
+ ** Example of oln::topo::chamfer_5_7_11() w;
+ ** w.delta(): 2
+ ** w.coef: 5.0206
+ ** w.win:
+ ** . 11 . 11 .
+ ** 11 7 5 7 11
+ ** . 5 . . .
+ ** . . . . .
+ ** . . . . .
+ ** \endverbatim
+ */
+ inline const chamfer<int>& chamfer_5_7_11();
+ /*! Chamfer_9_13_20
+ **
+ ** \verbatim
+ ** Example of oln::topo::chamfer_9_13_20() w;
+ ** w.delta(): 2
+ ** w.coef: 9.1409
+ ** w.win:
+ ** . 20 . 20 .
+ ** 20 13 9 13 20
+ ** . 9 . . .
+ ** . . . . .
+ ** . . . . .
+ ** \endverbatim
+ */
+ inline const chamfer<int>& chamfer_9_13_20();
+ /*! Chamfer_16_23_36
+ **
+ ** \verbatim
+ ** Example of oln::topo::chamfer_16_23_36() w;
+ ** w.delta(): 2
+ ** w.coef: 16.3351
+ ** w.win:
+ ** . 36 . 36 .
+ ** 36 23 16 23 36
+ ** . 16 . . .
+ ** . . . . .
+ ** . . . . .
+ ** \endverbatim
+ */
+ inline const chamfer<int>& chamfer_16_23_36();
+ /*! Best set 3x3
+ **
+ ** \verbatim
+ ** Example of oln::topo::best_set_3x3() w;
+ ** w.delta(): 1
+ ** w.coef: 1
+ ** w.win:
+ ** 1.3408 0.9481 1.3408
+ ** 0.9481 . .
+ ** . . .
+ ** \endverbatim
+ */
+ inline const chamfer<float>& best_set_3x3();
+ /*! Best set 5x5
+ **
+ ** \verbatim
+ ** Example of oln::topo::best_set_5x5() w;
+ ** w.delta(): 2
+ ** w.coef: 1
+ ** w.win:
+ ** . 2.2044 . 2.2044 .
+ ** 2.2044 1.406 0.9801 1.406 2.2044
+ ** . 0.9801 . . .
+ ** . . . . .
+ ** . . . . .
+ ** \endverbatim
+ */
+ inline const chamfer<float>& best_set_5x5();
+
+ // maximum absolute error for integer local distances (Table 2)
+ /* Maximum absolute error for integer local distances for chamfer_1_1.
+ **
+ ** \verbatim
+ ** oln::topo::mchamfer_1_1() =
+ ** w.delta(): 1
+ ** w.coef: 0.8536
+ ** w.win:
+ ** 1 1 1
+ ** 1 . .
+ ** . . .
+ ** \endverbatim
+ */
+ inline const chamfer<int>& mchamfer_1_1();
+ /* Maximum absolute error for integer local distances for chamfer_1_2.
+ **
+ ** \verbatim
+ ** oln::topo::mchamfer_1_2() =
+ ** w.delta(): 1
+ ** w.coef: 1.2071
+ ** w.win:
+ ** 2 1 2
+ ** 1 . .
+ ** . . .
+ ** \endverbatim
+ */
+ inline const chamfer<int>& mchamfer_1_2();
+ /* Maximum absolute error for integer local distances for chamfer_2_3.
+ **
+ ** \verbatim
+ ** oln::topo::mchamfer_2_3() =
+ ** w.delta(): 1
+ ** w.coef: 2.118
+ ** w.win:
+ ** 3 2 3
+ ** 2 . .
+ ** . . .
+ ** \endverbatim
+ */
+ inline const chamfer<int>& mchamfer_2_3();
+ /* Maximum absolute error for integer local distances for chamfer_5_7.
+ **
+ ** \verbatim
+ ** oln::topo::mchamfer_5_7() =
+ ** w.delta(): 1
+ ** w.coef: 5.1675
+ ** w.win:
+ ** 7 5 7
+ ** 5 . .
+ ** . . .
+ ** \endverbatim
+ */
+ inline const chamfer<int>& mchamfer_5_7();
+ /* Maximum absolute error for integer local distances for chamfer_12_17.
+ **
+ ** \verbatim
+ ** oln::topo::mchamfer_12_17() =
+ ** w.delta(): 1
+ ** w.coef: 12.5
+ ** w.win:
+ ** 17 12 17
+ ** 12 . .
+ ** . . .
+ ** \endverbatim
+ */
+ inline const chamfer<int>& mchamfer_12_17();
+ /* Maximum absolute error for integer local distances for chessboard.
+ **
+ ** \verbatim
+ ** oln::topo::mchessboard() =
+ ** w.delta(): 1
+ ** w.coef: 0.8536
+ ** w.win:
+ ** 1 1 1
+ ** 1 . .
+ ** . . .
+ ** \endverbatim
+ */
+ inline const chamfer<int>& mchessboard();
+ /* Maximum absolute error for integer local distances for cityblock.
+ **
+ ** \verbatim
+ ** oln::topo::mcityblock() =
+ ** w.delta(): 1
+ ** w.coef: 1.2071
+ ** w.win:
+ ** 2 1 2
+ ** 1 . .
+ ** . . .
+ ** \endverbatim
+ */
+ inline const chamfer<int>& mcityblock();
+ /* Maximum absolute error for integer local distances for chamfer_4_6_9.
+ **
+ ** \verbatim
+ ** oln::topo::mchamfer_4_6_9() =
+ ** w.delta(): 2
+ ** w.coef: 4.1213
+ ** w.win:
+ ** . 9 . 9 .
+ ** 9 6 4 6 9
+ ** . 4 . . .
+ ** . . . . .
+ ** . . . . .
+ ** \endverbatim
+ */
+ inline const chamfer<int>& mchamfer_4_6_9();
+ /* Maximum absolute error for integer local distances for chamfer_5_7_11.
+ **
+ ** \verbatim
+ ** oln::topo::mchamfer_5_7_11() =
+ ** w.delta(): 2
+ ** w.coef: 5.0092
+ ** w.win:
+ ** . 11 . 11 .
+ ** 11 7 5 7 11
+ ** . 5 . . .
+ ** . . . . .
+ ** . . . . .
+ ** \endverbatim
+ */
+ inline const chamfer<int>& mchamfer_5_7_11();
+ /* Maximum absolute error for integer local distances for chamfer_9_13_20.
+ **
+ ** \verbatim
+ ** oln::topo::mchamfer_9_13_20() =
+ ** w.delta(): 2
+ ** w.coef: 9.0819
+ ** w.win:
+ ** . 20 . 20 .
+ ** 20 13 9 13 20
+ ** . 9 . . .
+ ** . . . . .
+ ** . . . . .
+ ** \endverbatim
+ */
+ inline const chamfer<int>& mchamfer_9_13_20();
+ /* Maximum absolute error for integer local distances for chamfer_17_24_38.
+ **
+ ** \verbatim
+ ** oln::topo::mchamfer_17_24_38() =
+ ** w.delta(): 2
+ ** w.coef: 17.2174
+ ** w.win:
+ ** . 38 . 38 .
+ ** 38 24 17 24 38
+ ** . 17 . . .
+ ** . . . . .
+ ** . . . . .
+ ** \endverbatim
+ */
+ inline const chamfer<int>& mchamfer_17_24_38();
+ /* Maximum absolute error for integer local distances for best_set_3x3.
+ **
+ ** \verbatim
+ ** oln::topo:mbest_set_3x3() =
+ ** w.delta(): 1
+ ** w.coef: 1
+ ** w.win:
+ ** 1.35825 0.96043 1.35825
+ ** 0.96043 . .
+ ** . . .
+ ** \endverbatim
+ */
+ inline const chamfer<float>& mbest_set_3x3();
+ /* Maximum absolute error for integer local distances for best_set_5x5.
+ **
+ ** \verbatim
+ ** oln::topo:mbest_set_5x5() =
+ ** w.delta(): 2
+ ** w.coef: 1
+ ** w.win:
+ ** . 2.20585 . 2.20585 .
+ ** 2.20585 1.3951 0.986485 1.3951 2.20585
+ ** . 0.986485 . . .
+ ** . . . . .
+ ** . . . . .
+ ** \endverbatim
+ */
+ inline const chamfer<float>& mbest_set_5x5();
+
+ /*! Distance map
+ **
+ ** \param T Type of the distance.
+ ** \param T2 Type of the chamfer distance.
+ **
+ ** \note Do not forget to call \a compute.
+ **
+ ** \code
+ ** #include <oln/basics2d.hh>
+ ** #include <oln/topo/dmap.hh>
+ ** #include <oln/convert/stretch.hh>
+ **
+ ** int main()
+ ** {
+ ** oln::image2d<ntg::bin> in = oln::load(IMG_IN "face_se.pbm");
+ **
+ ** oln::topo::dmap<ntg::int_u<16>, int> m(in.size(),
oln::topo::chessboard());
+ ** m.compute(in);
+ ** save(oln::convert::stretch_balance<ntg::int_u8>(m.imap()),
+ ** IMG_OUT "oln_topo_dmap.pgm");
+ ** }
+ ** \endcode
+ ** \image html face_se_pbm.png
+ ** \image latex face_se_pbm.png
+ ** =>
+ ** \image html oln_topo_dmap.png
+ ** \image latex oln_topo_dmap.png
+ */
+ template<class T, class T2>
+ class dmap
+ {
+ public:
+ typedef image2d<ntg::bin>::point_type point_type;
+
+ /*! Constructor.
+ **
+ ** \arg size Size of the image on which the dmap will be compute.
+ ** \arg ch Chamfer distance used.
+ */
+ dmap(const image2d_size& size, const chamfer<T2>& ch);
+
+ /// Compute the distance map.
+ template <class V>
+ void
+ compute(const image2d<V>& input, float infty = 0.f);
+
+ /// Compute the distance map.
+ template <class V>
+ void
+ compute(const image2d<V>& input,
+ image2d<point2d>& nearest_point_map,
+ float infty = 0.f);
+
+ /// Return the distance map of type T.
+ const image2d<T>&
+ imap() const;
+
+ /// Return the distance map divided by the Chamfer coefficient.
+ image2d<float>
+ to_image() const;
+
+ /// Distance of a point p.
+ const T
+ operator[](const point_type& p) const;
+
+ /// Distance of a point2d(row, col).
+ const T
+ operator()(coord row, coord col) const;
+
+ private:
+ image2d<T> imap_;
+ chamfer<T2> ch_;
+ float inFty_;
+ T infTy_;
+ };
+ /// Distance map using the Euclidean distance.
+ template <class I>
+ image2d<float> exact_dmap(const abstract::image<I>& input);
+
+ } // end of namespace topo
+
+} // end of namespace oln
+
+# include <oln/topo/dmap.hxx>
+
+#endif // OLENA_TOPO_DMAP_HH
Index: trunk/milena/sandbox/nivault/dmap.hxx
===================================================================
--- trunk/milena/sandbox/nivault/dmap.hxx (revision 0)
+++ trunk/milena/sandbox/nivault/dmap.hxx (revision 1106)
@@ -0,0 +1,372 @@
+// Copyright (C) 2001, 2002, 2003, 2004 EPITA Research and Development Laboratory
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
+// MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+#ifndef MLN_TOPO_DMAP_HXX
+# define MLN_TOPO_DMAP_HXX
+
+# include <mlc/array/2d.hh>
+# include <ntg/float.hh>
+# include <oln/arith/ops.hh>
+# include <mln/geom/sym.hh>
+
+namespace mln
+{
+
+ namespace topo
+ {
+
+// using mlc::lbrk;
+// using mlc::end;
+// using mlc::x;
+
+ template <class T>
+ chamfer<T>::chamfer(const w_window2d<T>& win,
+ float coef) :
+ win(win),
+ coef(coef)
+ {}
+
+ template <class T>
+ coord
+ chamfer<T>::delta() const
+ {
+ coord d = win.delta();
+ return d;
+ }
+
+ // mk_chamfer...
+ // FIXME: this is highly not thread safe !
+ template<int d10, int d11> inline
+ const chamfer<int>&
+ mk_chamfer_3x3(float coef)
+ {
+ static const w_window2d<int> w_win = ( mlc::ints_2d =
+ d11, d10, d11, mlc::lbrk,
+ d10, mlc::x(), 0, end );
+ static const chamfer<int> ch_ = chamfer<int>(w_win, geom::sym(w_win),
coef);
+ return ch_;
+ }
+
+ inline // FIXME: how to define float by parameters?
+ const chamfer<float>&
+ mk_chamfer_3x3(float d10, float d11)
+ // FIXME: add (?) , float coef = 1.f
+ {
+ static const w_window2d<float> w_win = ( mlc::floats_2d =
+ d11, d10, d11, mlc::lbrk,
+ d10, mlc::x(), 0.f, end );
+ static const chamfer<float> ch_ =
+ chamfer<float>(w_win, geom::sym(w_win), 1.f);
+ return ch_;
+ }
+
+ template<int d10, int d11, int d21> inline
+ const chamfer<int>&
+ mk_chamfer_5x5(float coef)
+ {
+ static const w_window2d<int> w_win = ( mlc::ints_2d =
+ 0, d21, 0, d21, 0, mlc::lbrk,
+ d21, d11, d10, d11, d21,
+ 0, d10, mlc::x(), 0, 0, end );
+ static const chamfer<int> ch_ = chamfer<int>(w_win, geom::sym(w_win),
coef);
+ return ch_;
+ }
+
+ inline
+ const chamfer<float>&
+ mk_chamfer_5x5(float d10, float d11, float d21)
+ {
+ const float O = 0.f;
+ static const w_window2d<float> w_win = ( mlc::floats_2d =
+ O, d21, O, d21, O, mlc::lbrk,
+ d21, d11, d10, d11, d21,
+ O, d10, mlc::x(), O, O, end );
+ static const chamfer<float> ch_ =
+ chamfer<float>(w_win, geom::sym(w_win), 1.f);
+ return ch_;
+ }
+
+ // REF: B.J.H. Verwer, Local distances for distance transformations
+ // in two and three dimensions, Pattern Recognition Letters 12 (1991) 671-682
+
+ // unbiased minimal mean square error for integer local distances (Table 5)
+# define oln_topo_chamfer2_(Name, I, J, D, E) \
+ inline const chamfer<int>& Name##_##I##_##J() \
+ { \
+ static const chamfer<int> tmp = \
+ mk_chamfer_##D##x##D< I, J >(E); \
+ return tmp; \
+ }
+
+# define oln_topo_chamfer3_(Name, I, J, K, D, E) \
+ inline const chamfer<int>& Name##_##I##_##J##_##K() \
+ { \
+ static const chamfer<int> tmp = \
+ mk_chamfer_##D##x##D< I, J, K >(E); \
+ return tmp; \
+ }
+
+ oln_topo_chamfer2_(chamfer, 1, 1, 3, 0.9003)
+ oln_topo_chamfer2_(chamfer, 1, 2, 3, 1.2732)
+ oln_topo_chamfer2_(chamfer, 2, 3, 3, 2.1736)
+ oln_topo_chamfer2_(chamfer, 5, 7, 3, 5.2474)
+ oln_topo_chamfer2_(chamfer, 12, 17, 3, 12.6684)
+
+ inline const chamfer<int>&
+ chessboard()
+ {
+ return chamfer_1_1();
+ }
+
+ inline const chamfer<int>&
+ cityblock()
+ {
+ return chamfer_1_2();
+ }
+
+ oln_topo_chamfer3_(chamfer, 4, 6, 9, 5, 4.1203)
+ oln_topo_chamfer3_(chamfer, 5, 7, 11, 5, 5.0206)
+ oln_topo_chamfer3_(chamfer, 9, 13, 20, 5, 9.1409)
+ oln_topo_chamfer3_(chamfer, 16, 23, 36, 5, 16.3351)
+
+ inline const chamfer<float>& best_set_3x3()
+ { return mk_chamfer_3x3(0.9481, 1.3408); }
+ inline const chamfer<float>& best_set_5x5()
+ { return mk_chamfer_5x5(0.9801, 1.4060, 2.2044); }
+
+ // maximum absolute error for integer local distances (Table 2)
+ oln_topo_chamfer2_(mchamfer, 1, 1, 3, 0.8536)
+ oln_topo_chamfer2_(mchamfer, 1, 2, 3, 1.2071)
+ oln_topo_chamfer2_(mchamfer, 2, 3, 3, 2.1180)
+ oln_topo_chamfer2_(mchamfer, 5, 7, 3, 5.1675)
+ oln_topo_chamfer2_(mchamfer, 12, 17, 3, 12.5000)
+
+ inline const chamfer<int>& mchessboard() { return mchamfer_1_1(); }
+ inline const chamfer<int>& mcityblock() { return mchamfer_1_2(); }
+
+ oln_topo_chamfer3_(mchamfer, 4, 6, 9, 5, 4.1213)
+ oln_topo_chamfer3_(mchamfer, 5, 7, 11, 5, 5.0092)
+ oln_topo_chamfer3_(mchamfer, 9, 13, 20, 5, 9.0819)
+ oln_topo_chamfer3_(mchamfer, 17, 24, 38, 5, 17.2174)
+
+ inline const chamfer<float>& mbest_set_3x3() {
+ const float coef = 1.0412;
+ return mk_chamfer_3x3(1/coef, sqrt(2.f)/coef);
+ }
+ inline const chamfer<float>& mbest_set_5x5() {
+ const float coef = 1.0137;
+ return mk_chamfer_5x5(1/coef, sqrt(2.f)/coef, sqrt(5.f)/coef);
+ }
+
+# undef oln_topo_chamfer2_
+# undef oln_topo_chamfer3_
+
+ template <class T, class T2>
+ dmap<T, T2>::dmap(const image2d_size& size,
+ const chamfer<T2>& ch) :
+ imap_(size),
+ ch_(ch)
+ {
+ // FIXME: if T is float then precondition(ch.coef == 1.f)
+ }
+
+ template <class T, class T2>
+ template <class V>
+ void
+ dmap<T, T2>::compute(const image2d<V>& input,
+ float infty)
+ {
+ image2d<point_type> dummy(input.size());
+ compute(input, dummy, infty);
+ }
+
+ template <class T, class T2>
+ template <class V>
+ void dmap<T, T2>::compute(const image2d<V>& input,
+ image2d<point_type>& nearest_point_map,
+ float infty)
+ {
+ precondition(input.size() == imap_.size());
+ if (infty == 0.f)
+ {
+ inFty_ = ntg_max_val(T);
+ infTy_ = ntg_max_val(T);
+ }
+ else
+ {
+ inFty_ = infty;
+ infTy_ = T(infty); // FIXME: use ceil if T is integer!
+ }
+
+ // init
+ {
+ typename image2d<V>::iter_type p(input);
+ for (p = begin; p != end; ++p)
+ if (input[p] != ntg_zero_val(V))
+ {
+ imap_[p] = T(0);
+ nearest_point_map[p] = p;
+ }
+ else
+ imap_[p] = infTy_;
+ imap_.border_adapt_copy(ch_.delta()); // FIXME: this is geodesic only!
+ }
+
+ // win
+ {
+ typename image2d<V>::win_iter_type p(input);
+ for (p = begin; p != end; ++p)
+ {
+ if (imap_[p] == T(0))
+ continue;
+ T min = imap_[p];
+ for (unsigned i = 0; i < ch_.win.card(); ++i)
+ {
+ point_type q = p + ch_.win.dp(i);
+ if (imap_[q] == infTy_) // FIXME: || imap_[q] >= min
+ continue;
+ if (imap_[q] + ch_.win.w(i) < min)
+ {
+ nearest_point_map[p] = nearest_point_map[q];
+ min = imap_[q] + ch_.win.w(i);
+ }
+ }
+ imap_[p] = min;
+ }
+ }
+
+ const w_window2d<T2>& bkd = geom::sym(ch_.win);
+
+ // bkd
+ {
+ typename image2d<V>::bkd_iter_type p(input);
+ for_all(p)
+ {
+ if (imap_[p] == T(0))
+ continue;
+ T min = imap_[p];
+ for (unsigned i = 0; i < ch_.bkd.card(); ++i)
+ {
+ point_type q = p + ch_.bkd.dp(i);
+ if (imap_[q] == infTy_) // FIXME: || imap_[q] >= min
+ continue;
+ if (imap_[q] + ch_.bkd.w(i) < min)
+ {
+ nearest_point_map[p] = nearest_point_map[q];
+ min = imap_[q] + ch_.bkd.w(i);
+ }
+ }
+ imap_[p] = min;
+ }
+ }
+ }
+
+ template <class T, class T2>
+ const image2d<T>&
+ dmap<T, T2>::imap() const
+ {
+ return imap_;
+ }
+
+ template <class T, class T2>
+ image2d<float>
+ dmap<T, T2>::to_image() const
+ {
+ // FIXME: if T is float, call invariant(ch_.coef == 1.f);
+ // and then return imap();
+ // otherwise: return arith::div(imap_, ch_.coef);
+ image2d<float> output(imap_.size());
+ typename image2d<float>::iter_type p(imap_);
+ for_all(p)
+ output[p] = (imap_[p] == infTy_ ?
+ inFty_ :
+ imap_[p] / ch_.coef);
+ return output;
+ }
+
+ template <class T, class T2>
+ const T
+ dmap<T, T2>::operator[](const point_type& p) const
+ {
+ return imap_[p] / ch_.coef;
+ }
+
+ template <class T, class T2>
+ const T
+ dmap<T, T2>::operator()(coord row, coord col) const
+ {
+ return imap_(row, col) / ch_.coef;
+ }
+
+ inline float
+ euclidian_dist2(const point2d& p1, const point2d& p2)
+ {
+ float dr = p1.row() - p2.row();
+ float dc = p1.col() - p2.col();
+ return dr * dr + dc * dc;
+ }
+
+ // FIXME: why abstract::image!
+
+ template <class I>
+ image2d<float>
+ exact_dmap(const abstract::image<I>& input)
+ {
+ image2d<float> output(input.size());
+ image2d<float>::fwd_iter_type p(input);
+ for_all(p)
+ {
+ if (input[p] == true)
+ {
+ output[p] = 0.f;
+ continue;
+ }
+ image2d<float>::fwd_iter_type q(input);
+ bool found = false;
+ float d = 0.f;
+ for_all(q)
+ {
+ if (input[q] == false || q == p)
+ continue;
+ if (! found)
+ {
+ d = euclidian_dist2(p, q);
+ found = true;
+ continue;
+ }
+ d = std::min(euclidian_dist2(p, q), d);
+ }
+ output[p] = sqrt(d);
+ }
+ return output;
+ }
+
+ } // end of namespace topo
+
+} // end of namespace mln
+
+#endif // ! MLN_TOPO_DMAP_HXX