Fixed some bugs in videostab module and refactored it
authorAlexey Spizhevoy <no@email>
Wed, 4 Apr 2012 09:28:47 +0000 (09:28 +0000)
committerAlexey Spizhevoy <no@email>
Wed, 4 Apr 2012 09:28:47 +0000 (09:28 +0000)
13 files changed:
modules/videostab/include/opencv2/videostab/global_motion.hpp
modules/videostab/include/opencv2/videostab/motion_stabilizing.hpp
modules/videostab/include/opencv2/videostab/ring_buffer.hpp [new file with mode: 0644]
modules/videostab/include/opencv2/videostab/videostab.hpp
modules/videostab/src/deblurring.cpp
modules/videostab/src/fast_marching.cpp
modules/videostab/src/frame_source.cpp
modules/videostab/src/global_motion.cpp
modules/videostab/src/inpainting.cpp
modules/videostab/src/motion_stabilizing.cpp
modules/videostab/src/optical_flow.cpp
modules/videostab/src/precomp.hpp
modules/videostab/src/stabilizer.cpp

index 2acaad2..2bf0781 100644 (file)
@@ -132,8 +132,6 @@ private:
     float minInlierRatio_;
 };
 
-CV_EXPORTS Mat getMotion(int from, int to, const Mat *motions, int size);
-
 CV_EXPORTS Mat getMotion(int from, int to, const std::vector<Mat> &motions);
 
 } // namespace videostab
index fa6aeb2..f9775b1 100644 (file)
@@ -44,6 +44,7 @@
 #define __OPENCV_VIDEOSTAB_MOTION_STABILIZING_HPP__
 
 #include <vector>
+#include <utility>
 #include "opencv2/core/core.hpp"
 
 namespace cv
@@ -55,15 +56,24 @@ class CV_EXPORTS IMotionStabilizer
 {
 public:
     virtual ~IMotionStabilizer() {}
-    virtual void stabilize(const Mat *motions, int size, Mat *stabilizationMotions) const = 0;
+
+    // assumes that [range.first, range.second) is in or equals to [0, size-2]
+    virtual void stabilize(
+            int size, const std::vector<Mat> &motions, std::pair<int,int> range,
+            Mat *stabilizationMotions) const = 0;
 };
 
 class CV_EXPORTS MotionFilterBase : public IMotionStabilizer
 {
 public:
     virtual ~MotionFilterBase() {}
-    virtual Mat stabilize(int index, const Mat *motions, int size) const = 0;
-    virtual void stabilize(const Mat *motions, int size, Mat *stabilizationMotions) const;
+
+    virtual Mat stabilize(
+            int idx, const std::vector<Mat> &motions, std::pair<int,int> range) const = 0;
+
+    virtual void stabilize(
+            int size, const std::vector<Mat> &motions, std::pair<int,int> range,
+            Mat *stabilizationMotions) const;
 };
 
 class CV_EXPORTS GaussianMotionFilter : public MotionFilterBase
@@ -75,7 +85,8 @@ public:
     int radius() const { return radius_; }
     float stdev() const { return stdev_; }
 
-    virtual Mat stabilize(int index, const Mat *motions, int size) const;
+    virtual Mat stabilize(
+            int idx, const std::vector<Mat> &motions, std::pair<int,int> range) const;
 
 private:
     int radius_;
diff --git a/modules/videostab/include/opencv2/videostab/ring_buffer.hpp b/modules/videostab/include/opencv2/videostab/ring_buffer.hpp
new file mode 100644 (file)
index 0000000..c03052c
--- /dev/null
@@ -0,0 +1,67 @@
+/*M///////////////////////////////////////////////////////////////////////////////////////
+//
+//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
+//
+//  By downloading, copying, installing or using the software you agree to this license.
+//  If you do not agree to this license, do not download, install,
+//  copy or use the software.
+//
+//
+//                           License Agreement
+//                For Open Source Computer Vision Library
+//
+// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
+// Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved.
+// Third party copyrights are property of their respective owners.
+//
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
+//
+//   * Redistribution's of source code must retain the above copyright notice,
+//     this list of conditions and the following disclaimer.
+//
+//   * Redistribution's in binary form must reproduce the above copyright notice,
+//     this list of conditions and the following disclaimer in the documentation
+//     and/or other materials provided with the distribution.
+//
+//   * The name of the copyright holders may not be used to endorse or promote products
+//     derived from this software without specific prior written permission.
+//
+// This software is provided by the copyright holders and contributors "as is" and
+// any express or implied warranties, including, but not limited to, the implied
+// warranties of merchantability and fitness for a particular purpose are disclaimed.
+// In no event shall the Intel Corporation or contributors be liable for any direct,
+// indirect, incidental, special, exemplary, or consequential damages
+// (including, but not limited to, procurement of substitute goods or services;
+// loss of use, data, or profits; or business interruption) however caused
+// and on any theory of liability, whether in contract, strict liability,
+// or tort (including negligence or otherwise) arising in any way out of
+// the use of this software, even if advised of the possibility of such damage.
+//
+//M*/
+
+#ifndef __OPENCV_VIDEOSTAB_RING_BUFFER_HPP__
+#define __OPENCV_VIDEOSTAB_RING_BUFFER_HPP__
+
+#include <vector>
+#include "opencv2/imgproc/imgproc.hpp"
+
+namespace cv
+{
+namespace videostab
+{
+
+template <typename T> inline T& at(int idx, std::vector<T> &items)
+{
+    return items[cv::borderInterpolate(idx, static_cast<int>(items.size()), cv::BORDER_WRAP)];
+}
+
+template <typename T> inline const T& at(int idx, const std::vector<T> &items)
+{
+    return items[cv::borderInterpolate(idx, static_cast<int>(items.size()), cv::BORDER_WRAP)];
+}
+
+} // namespace videostab
+} // namespace cv
+
+#endif
index 3ea34a8..35f9b22 100644 (file)
@@ -44,5 +44,6 @@
 #define __OPENCV_VIDEOSTAB_HPP__
 
 #include "opencv2/videostab/stabilizer.hpp"
+#include "opencv2/videostab/ring_buffer.hpp"
 
 #endif
index 813e908..e26c4b3 100644 (file)
@@ -43,6 +43,7 @@
 #include "precomp.hpp"
 #include "opencv2/videostab/deblurring.hpp"
 #include "opencv2/videostab/global_motion.hpp"
+#include "opencv2/videostab/ring_buffer.hpp"
 
 using namespace std;
 
index dd18e2f..85bb26d 100644 (file)
@@ -42,6 +42,7 @@
 
 #include "precomp.hpp"
 #include "opencv2/videostab/fast_marching.hpp"
+#include "opencv2/videostab/ring_buffer.hpp"
 
 using namespace std;
 
index b363016..4d6a30e 100644 (file)
@@ -42,6 +42,7 @@
 
 #include "precomp.hpp"
 #include "opencv2/videostab/frame_source.hpp"
+#include "opencv2/videostab/ring_buffer.hpp"
 
 using namespace std;
 
index c522a76..a6c051b 100644 (file)
@@ -43,6 +43,7 @@
 #include "precomp.hpp"
 #include "opencv2/highgui/highgui.hpp"
 #include "opencv2/videostab/global_motion.hpp"
+#include "opencv2/videostab/ring_buffer.hpp"
 
 using namespace std;
 
@@ -333,28 +334,22 @@ Mat PyrLkRobustMotionEstimator::estimate(const Mat &frame0, const Mat &frame1)
 }
 
 
-Mat getMotion(int from, int to, const Mat *motions, int size)
+Mat getMotion(int from, int to, const vector<Mat> &motions)
 {
     Mat M = Mat::eye(3, 3, CV_32F);
     if (to > from)
     {
         for (int i = from; i < to; ++i)
-            M = at(i, motions, size) * M;
+            M = at(i, motions) * M;
     }
     else if (from > to)
     {
         for (int i = to; i < from; ++i)
-            M = at(i, motions, size) * M;
+            M = at(i, motions) * M;
         M = M.inv();
     }
     return M;
 }
 
-
-Mat getMotion(int from, int to, const vector<Mat> &motions)
-{
-    return getMotion(from, to, &motions[0], motions.size());
-}
-
 } // namespace videostab
 } // namespace cv
index a2e3c2c..c465a22 100644 (file)
@@ -45,6 +45,7 @@
 #include "opencv2/videostab/inpainting.hpp"
 #include "opencv2/videostab/global_motion.hpp"
 #include "opencv2/videostab/fast_marching.hpp"
+#include "opencv2/videostab/ring_buffer.hpp"
 
 using namespace std;
 
index b35a20a..eb16749 100644 (file)
@@ -43,6 +43,7 @@
 #include "precomp.hpp"
 #include "opencv2/videostab/motion_stabilizing.hpp"
 #include "opencv2/videostab/global_motion.hpp"
+#include "opencv2/videostab/ring_buffer.hpp"
 
 using namespace std;
 
@@ -51,17 +52,18 @@ namespace cv
 namespace videostab
 {
 
-void MotionFilterBase::stabilize(const Mat *motions, int size, Mat *stabilizationMotions) const
+void MotionFilterBase::stabilize(
+        int size, const vector<Mat> &motions, pair<int,int> range, Mat *stabilizationMotions) const
 {
     for (int i = 0; i < size; ++i)
-        stabilizationMotions[i] = stabilize(i, motions, size);
+        stabilizationMotions[i] = stabilize(i, motions, range);
 }
 
 
 void GaussianMotionFilter::setParams(int radius, float stdev)
 {
     radius_ = radius;
-    stdev_ = stdev > 0.f ? stdev : sqrt(static_cast<float>(radius_));
+    stdev_ = stdev > 0.f ? stdev : sqrt(static_cast<float>(radius));
 
     float sum = 0;
     weight_.resize(2*radius_ + 1);
@@ -72,17 +74,19 @@ void GaussianMotionFilter::setParams(int radius, float stdev)
 }
 
 
-Mat GaussianMotionFilter::stabilize(int index, const Mat *motions, int size) const
+Mat GaussianMotionFilter::stabilize(int idx, const vector<Mat> &motions, pair<int,int> range) const
 {
-    const Mat &cur = at(index, motions, size);
+    const Mat &cur = at(idx, motions);
     Mat res = Mat::zeros(cur.size(), cur.type());
     float sum = 0.f;
-    for (int i = std::max(index - radius_, 0); i <= index + radius_; ++i)
+    int iMin = std::max(idx - radius_, range.first);
+    int iMax = std::min(idx + radius_, range.second);
+    for (int i = iMin; i <= iMax; ++i)
     {
-        res += weight_[radius_ + i - index] * getMotion(index, i, motions, size);
-        sum += weight_[radius_ + i - index];
+        res += weight_[radius_ + i - idx] * getMotion(idx, i, motions);
+        sum += weight_[radius_ + i - idx];
     }
-    return res / sum;
+    return sum > 0.f ? res / sum : Mat::eye(cur.size(), cur.type());
 }
 
 
index 083c0e0..92c1780 100644 (file)
@@ -43,6 +43,7 @@
 #include "precomp.hpp"
 #include "opencv2/video/video.hpp"
 #include "opencv2/videostab/optical_flow.hpp"
+#include "opencv2/videostab/ring_buffer.hpp"
 
 using namespace std;
 
index bdf1e49..5c74f04 100644 (file)
@@ -55,6 +55,8 @@
 #include "opencv2/video/video.hpp"
 #include "opencv2/features2d/features2d.hpp"
 
+// some aux. functions
+
 inline float sqr(float x) { return x * x; }
 
 inline float intensity(const cv::Point3_<uchar> &bgr)
@@ -62,25 +64,5 @@ inline float intensity(const cv::Point3_<uchar> &bgr)
     return 0.3f*bgr.x + 0.59f*bgr.y + 0.11f*bgr.z;
 }
 
-template <typename T> inline T& at(int index, T *items, int size)
-{
-    return items[cv::borderInterpolate(index, size, cv::BORDER_WRAP)];
-}
-
-template <typename T> inline const T& at(int index, const T *items, int size)
-{
-    return items[cv::borderInterpolate(index, size, cv::BORDER_WRAP)];
-}
-
-template <typename T> inline T& at(int index, std::vector<T> &items)
-{
-    return at(index, &items[0], items.size());
-}
-
-template <typename T> inline const T& at(int index, const std::vector<T> &items)
-{
-    return items[cv::borderInterpolate(index, items.size(), cv::BORDER_WRAP)];
-}
-
 #endif
 
index bca316c..becc47e 100644 (file)
@@ -42,6 +42,7 @@
 
 #include "precomp.hpp"
 #include "opencv2/videostab/stabilizer.hpp"
+#include "opencv2/videostab/ring_buffer.hpp"
 
 using namespace std;
 
@@ -145,7 +146,7 @@ bool StabilizerBase::doOneIteration()
     {
         curStabilizedPos_++;
         at(curStabilizedPos_ + radius_, frames_) = at(curPos_, frames_);
-        at(curStabilizedPos_ + radius_ - 1, motions_) = at(curPos_ - 1, motions_);
+        at(curStabilizedPos_ + radius_ - 1, motions_) = Mat::eye(3, 3, CV_32F);
         stabilizeFrame();
 
         log_->print(".");
@@ -212,7 +213,7 @@ void OnePassStabilizer::reset()
     stabilizedFrames_.clear();
     stabilizationMotions_.clear();
     doDeblurring_ = false;
-    doInpainting_ = false;
+    doInpainting_ = false;    
 }
 
 
@@ -251,7 +252,7 @@ void OnePassStabilizer::estimateMotion()
 
 void OnePassStabilizer::stabilizeFrame()
 {
-    Mat stabilizationMotion = motionFilter_->stabilize(curStabilizedPos_, &motions_[0], motions_.size());
+    Mat stabilizationMotion = motionFilter_->stabilize(curStabilizedPos_, motions_, make_pair(0, curPos_));
     StabilizerBase::stabilizeFrame(stabilizationMotion);
 }
 
@@ -326,7 +327,9 @@ void TwoPassStabilizer::runPrePassIfNecessary()
         log_->print("\n");
 
         stabilizationMotions_.resize(frameCount_);
-        motionStabilizer_->stabilize(&motions_[0], frameCount_, &stabilizationMotions_[0]);
+
+        motionStabilizer_->stabilize(
+            frameCount_, motions_, make_pair(0, frameCount_ - 1), &stabilizationMotions_[0]);
 
         if (mustEstTrimRatio_)
         {