diff --git a/modules/videostab/include/opencv2/videostab/global_motion.hpp b/modules/videostab/include/opencv2/videostab/global_motion.hpp index 19fcfefaca..9616eae5c4 100644 --- a/modules/videostab/include/opencv2/videostab/global_motion.hpp +++ b/modules/videostab/include/opencv2/videostab/global_motion.hpp @@ -66,7 +66,10 @@ CV_EXPORTS Mat estimateGlobalMotionLeastSquares( InputOutputArray points0, InputOutputArray points1, int model = MM_AFFINE, float *rmse = 0); -CV_EXPORTS Mat estimateGlobalMotionRobust( +CV_EXPORTS Mat estimateGlobalMotionMedian( + InputArray points0, InputArray points1, int model, int size, int niters); + +CV_EXPORTS Mat estimateGlobalMotionRansac( InputArray points0, InputArray points1, int model = MM_AFFINE, const RansacParams ¶ms = RansacParams::default2dMotion(MM_AFFINE), float *rmse = 0, int *ninliers = 0); diff --git a/modules/videostab/src/global_motion.cpp b/modules/videostab/src/global_motion.cpp index 6a40eac8b7..1eb2f0f46b 100644 --- a/modules/videostab/src/global_motion.cpp +++ b/modules/videostab/src/global_motion.cpp @@ -305,7 +305,73 @@ Mat estimateGlobalMotionLeastSquares( } -Mat estimateGlobalMotionRobust( +Mat estimateGlobalMotionMedian( + InputArray points0, InputArray points1, int model, int size, int niters) +{ + // perform 'niters' iterations over points subsets ('size' elements each) estimating + // motions, after that select median motion parameters from the distribution + + CV_Assert(model <= MM_AFFINE); + CV_Assert(points0.type() == points1.type()); + const int npoints = points0.getMat().checkVector(2); + CV_Assert(points1.getMat().checkVector(2) == npoints); + + const Point2f *points0_ = points0.getMat().ptr(); + const Point2f *points1_ = points1.getMat().ptr(); + + // all estimated motions + vector Ms[3][3]; + for (int i = 0; i < 3; ++i) + for (int j = 0; j < 3; ++j) + Ms[i][j].resize(niters); + + // current hypothesis + vector indices(size); + vector subset0(size); + vector subset1(size); + + RNG rng(0); + + for (int iter = 0; iter < niters; ++iter) + { + for (int i = 0; i < size; ++i) + { + bool ok = false; + while (!ok) + { + ok = true; + indices[i] = static_cast(rng) % npoints; + for (int j = 0; j < i; ++j) + if (indices[i] == indices[j]) + { ok = false; break; } + } + } + for (int i = 0; i < size; ++i) + { + subset0[i] = points0_[indices[i]]; + subset1[i] = points1_[indices[i]]; + } + + Mat_ M = estimateGlobalMotionLeastSquares(subset0, subset1, model, 0); + for (int i = 0; i < 3; ++i) + for (int j = 0; j < 3; ++j) + Ms[i][j][iter] = M(i, j); + } + + Mat_ medianM(3, 3); + + for (int i = 0; i < 3; ++i) + for (int j = 0; j < 3; ++j) + { + nth_element(Ms[i][j].begin(), Ms[i][j].begin() + niters/2, Ms[i][j].end()); + medianM(i, j) = Ms[i][j][niters/2]; + } + + return medianM; +} + + +Mat estimateGlobalMotionRansac( InputArray points0, InputArray points1, int model, const RansacParams ¶ms, float *rmse, int *ninliers) { @@ -424,7 +490,7 @@ Mat MotionEstimatorRansacL2::estimate(InputArray points0, InputArray points1, bo Mat_ M; if (motionModel() != MM_HOMOGRAPHY) - M = estimateGlobalMotionRobust( + M = estimateGlobalMotionRansac( points0, points1, motionModel(), ransacParams_, 0, &ninliers); else { diff --git a/modules/videostab/src/precomp.hpp b/modules/videostab/src/precomp.hpp index 6a1fa7c46a..848c54836a 100644 --- a/modules/videostab/src/precomp.hpp +++ b/modules/videostab/src/precomp.hpp @@ -50,6 +50,7 @@ #include #include #include +#include #include "opencv2/core/core.hpp" #include "opencv2/imgproc/imgproc.hpp" #include "opencv2/video/video.hpp"