* mln/optical_flow/lk.hh: Here.
---
milena/ChangeLog | 6 ++
milena/mln/optical_flow/lk.hh | 185 +++++++++++++++++++++++++++++++++++++++++
2 files changed, 191 insertions(+), 0 deletions(-)
create mode 100644 milena/mln/optical_flow/lk.hh
diff --git a/milena/ChangeLog b/milena/ChangeLog
index b515294..15cac50 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,3 +1,9 @@
+2013-01-29 Sylvain Lobry <lobry(a)lrde.epita.fr>
+
+ Added Lucas-Kanade algorithm
+
+ * mln/optical_flow/lk.hh: Here.
+
2012-05-03 Sylvain Lobry <lobry(a)lrde.epita.fr>
Updated all.hh.
diff --git a/milena/mln/optical_flow/lk.hh b/milena/mln/optical_flow/lk.hh
new file mode 100644
index 0000000..679ed04
--- /dev/null
+++ b/milena/mln/optical_flow/lk.hh
@@ -0,0 +1,185 @@
+// Copyright (C) 2012 EPITA Research and Development Laboratory
+// (LRDE)
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena 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 Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project 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_OPTICAL_FLOW_LK_HH_
+# define MLN_OPTICAL_FLOW_LK_HH_
+
+/// \file
+///
+/// \brief Implementation of Lucas-Kanade algorithm.
+
+# include <mln/core/alias/box2d.hh>
+# include <mln/value/int_u8.hh>
+# include <mln/core/alias/vec2d.hh>
+# include <mln/core/concept/image.hh>
+# include <mln/win/rectangle2d.hh>
+# include <mln/pw/value.hh>
+# include <mln/core/image/dmorph/image_if.hh>
+
+# include <cmath>
+
+
+namespace mln
+{
+
+ namespace optical_flow
+ {
+
+ /// \brief Compute Lucas-Kanade algorithm
+ ///
+ /// @param ima1 First frame
+ /// @param ima2 Second frame
+ /// @param mask The mask on which we want to compute the optical flow
+ /// @param winsize size of the window used
+ /// @param weigths The weights inside the window
+ /// @param optical_flow the result
+
+ template <typename I>
+ void
+ LucasKanade (I& ima1,
+ I& ima2,
+ mln::image2d<bool>& mask,
+ unsigned winsize,
+ mln::image2d<double>& weights,
+ mln::image2d <mln::vec2d_f>& optical_flow);
+
+# ifndef MLN_INCLUDE_ONLY
+
+ //If true, of (optical flow) coarser but computation faster.
+# define PER_BLOCK (false)
+
+ template <typename I>
+ void
+ LucasKanade (I& ima1,
+ I& ima2,
+ mln::image2d<bool>& mask,
+ unsigned winsize,
+ mln::image2d<double>& weights,
+ mln::image2d <mln::vec2d_f>& optical_flow)
+ {
+ mln::win::rectangle2d win (winsize, winsize);
+
+ typedef mln::image_if<I, mln::pw::value_ <mln::image2d<bool> > >
II;
+
+ II ima = (ima1 | mln::pw::value (mask));
+
+ mln_piter (II) p (ima.domain ());
+
+ mln_qiter_ (mln::win::rectangle2d) q (win, p);
+ for_all (p)
+ {
+
+#if PER_BLOCK
+ if (p.col() % winsize == winsize / 2 && p.row () % winsize == winsize / 2)
+ {
+#endif
+ double A[winsize * winsize][2];
+ double B[winsize * winsize];
+ double W[winsize * winsize];
+ unsigned nb_comp = 0;
+
+ //filling matrices
+ for_all (q)
+ {
+ if (ima1.has(q))
+ {
+ //Ex
+ A[nb_comp][0] = ima1 (q + mln::dpoint2d (0, 1)) - ima1 (q)
+ + ima2 (q + mln::dpoint2d (0, 1)) - ima2 (q);
+ //Ey
+ A[nb_comp][1] = ima1 (q + mln::dpoint2d (1, 0)) - ima1 (q)
+ + ima2 (q + mln::dpoint2d (1, 0)) - ima2 (q);
+
+ //Et
+ B[nb_comp] = - (ima2 (q) - ima1 (q));
+ //weights
+ W[nb_comp] = weights (q);
+ ++nb_comp;
+ }
+ }
+
+ //Computing flow
+
+ //Filling the structure tensor (transpose(A) * A)
+ int struct_tensor[2][2] = {{0, 0}, {0, 0}};
+ for (unsigned i = 0; i < nb_comp; ++i)
+ {
+ struct_tensor [0][0] += W[i] * A[i][0] * A[i][0];
+ struct_tensor [1][0] += W[i] * A[i][0] * A[i][1];
+ struct_tensor [0][1] += W[i] * A[i][0] * A[i][1];
+ struct_tensor [1][1] += W[i] * A[i][1] * A[i][1];
+ }
+
+ //Computing the inverse of the structure tensor.
+ double struct_tensor_inv[2][2] = {{0, 0}, {0, 0}};
+ double det = struct_tensor[0][0] * struct_tensor[1][1]
+ - struct_tensor[1][0] * struct_tensor[0][1];
+
+ double Vx = 0;
+ double Vy = 0;
+ if (det * det > 0.000001)
+ {
+ struct_tensor_inv[0][0] = struct_tensor[1][1] / det;
+ struct_tensor_inv[0][1] = -struct_tensor[0][1] / det;
+ struct_tensor_inv[1][0] = -struct_tensor[1][0] / det;
+ struct_tensor_inv[1][1] = struct_tensor[0][0] / det;
+
+ int transAtimesB[2] = {0, 0};
+ for (unsigned i = 0; i < nb_comp; ++i)
+ {
+ transAtimesB[0] += W[i] * A[i][0] * B[i];
+ transAtimesB[1] += W[i] * A[i][1] * B[i];
+ }
+
+ Vx = struct_tensor_inv[0][0] * transAtimesB[0]
+ + struct_tensor_inv[0][1] * transAtimesB[1];
+ Vy = struct_tensor_inv[1][0] * transAtimesB[0]
+ + struct_tensor_inv[1][1] * transAtimesB[1];
+ }
+#if PER_BLOCK
+ for_all (q)
+ {
+ optical_flow (q)[0] = Vx;
+ optical_flow (q)[1] = Vy;
+ }
+ }
+#else
+ optical_flow (p)[0] = Vx;
+ optical_flow (p)[1] = Vy;
+#endif
+ }
+
+
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } //end of namespace optical_flow
+
+} //end of namespace mln
+
+
+#endif // ! MLN_OPTICAL_FLOW_LK_HH_
--
1.7.2.5