Skip to content

Commit a0d9138

Browse files
authored
Merge pull request #2424 from GArik:master
videostab: Fix out of range data usage * videostab: Add simple UTs for video stabilizers Reproduces issue #5178 * videostab: Fix out of range data usage Fixes issue #5178 * videostab: Use cv::Range for ranges instead of std::pair
1 parent bdfd1e7 commit a0d9138

File tree

7 files changed

+111
-29
lines changed

7 files changed

+111
-29
lines changed

modules/videostab/include/opencv2/videostab/deblurring.hpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ class CV_EXPORTS DeblurerBase
6666
virtual void setRadius(int val) { radius_ = val; }
6767
virtual int radius() const { return radius_; }
6868

69-
virtual void deblur(int idx, Mat &frame) = 0;
69+
virtual void deblur(int idx, Mat &frame, const Range &range) = 0;
7070

7171

7272
// data from stabilizer
@@ -90,7 +90,7 @@ class CV_EXPORTS DeblurerBase
9090
class CV_EXPORTS NullDeblurer : public DeblurerBase
9191
{
9292
public:
93-
virtual void deblur(int /*idx*/, Mat &/*frame*/) CV_OVERRIDE {}
93+
virtual void deblur(int /*idx*/, Mat &/*frame*/, const Range &/*range*/) CV_OVERRIDE {}
9494
};
9595

9696
class CV_EXPORTS WeightingDeblurer : public DeblurerBase
@@ -101,7 +101,7 @@ class CV_EXPORTS WeightingDeblurer : public DeblurerBase
101101
void setSensitivity(float val) { sensitivity_ = val; }
102102
float sensitivity() const { return sensitivity_; }
103103

104-
virtual void deblur(int idx, Mat &frame) CV_OVERRIDE;
104+
virtual void deblur(int idx, Mat &frame, const Range &range) CV_OVERRIDE;
105105

106106
private:
107107
float sensitivity_;

modules/videostab/include/opencv2/videostab/motion_stabilizing.hpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ class CV_EXPORTS IMotionStabilizer
6363

6464
//! assumes that [0, size-1) is in or equals to [range.first, range.second)
6565
virtual void stabilize(
66-
int size, const std::vector<Mat> &motions, std::pair<int,int> range,
66+
int size, const std::vector<Mat> &motions, const Range &range,
6767
Mat *stabilizationMotions) = 0;
6868
};
6969

@@ -74,7 +74,7 @@ class CV_EXPORTS MotionStabilizationPipeline : public IMotionStabilizer
7474
bool empty() const { return stabilizers_.empty(); }
7575

7676
virtual void stabilize(
77-
int size, const std::vector<Mat> &motions, std::pair<int,int> range,
77+
int size, const std::vector<Mat> &motions, const Range &range,
7878
Mat *stabilizationMotions) CV_OVERRIDE;
7979

8080
private:
@@ -87,10 +87,10 @@ class CV_EXPORTS MotionFilterBase : public IMotionStabilizer
8787
virtual ~MotionFilterBase() {}
8888

8989
virtual Mat stabilize(
90-
int idx, const std::vector<Mat> &motions, std::pair<int,int> range) = 0;
90+
int idx, const std::vector<Mat> &motions, const Range &range) = 0;
9191

9292
virtual void stabilize(
93-
int size, const std::vector<Mat> &motions, std::pair<int,int> range,
93+
int size, const std::vector<Mat> &motions, const Range &range,
9494
Mat *stabilizationMotions) CV_OVERRIDE;
9595
};
9696

@@ -104,7 +104,7 @@ class CV_EXPORTS GaussianMotionFilter : public MotionFilterBase
104104
float stdev() const { return stdev_; }
105105

106106
virtual Mat stabilize(
107-
int idx, const std::vector<Mat> &motions, std::pair<int,int> range) CV_OVERRIDE;
107+
int idx, const std::vector<Mat> &motions, const Range &range) CV_OVERRIDE;
108108

109109
private:
110110
int radius_;
@@ -141,7 +141,7 @@ class CV_EXPORTS LpMotionStabilizer : public IMotionStabilizer
141141
float weight4() const { return w4_; }
142142

143143
virtual void stabilize(
144-
int size, const std::vector<Mat> &motions, std::pair<int,int> range,
144+
int size, const std::vector<Mat> &motions, const Range &range,
145145
Mat *stabilizationMotions) CV_OVERRIDE;
146146

147147
private:

modules/videostab/samples/videostab.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,9 +125,9 @@ void printHelp()
125125
" -bm=, --border-mode=(replicate|reflect|const)\n"
126126
" Set border extrapolation mode. The default is replicate.\n\n"
127127
" --mosaic=(yes|no)\n"
128-
" Do consistent mosaicing. The default is no.\n"
128+
" Do consistent mosaicking. The default is no.\n"
129129
" --mosaic-stdev=<float_number>\n"
130-
" Consistent mosaicing stdev threshold. The default is 10.0.\n\n"
130+
" Consistent mosaicking stdev threshold. The default is 10.0.\n\n"
131131
" -mi=, --motion-inpaint=(yes|no)\n"
132132
" Do motion inpainting (requires CUDA support). The default is no.\n"
133133
" --mi-dist-thresh=<float_number>\n"

modules/videostab/src/deblurring.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ WeightingDeblurer::WeightingDeblurer()
7070
}
7171

7272

73-
void WeightingDeblurer::deblur(int idx, Mat &frame)
73+
void WeightingDeblurer::deblur(int idx, Mat &frame, const Range &range)
7474
{
7575
CV_INSTRUMENT_REGION();
7676

@@ -93,7 +93,9 @@ void WeightingDeblurer::deblur(int idx, Mat &frame)
9393
}
9494
}
9595

96-
for (int k = idx - radius_; k <= idx + radius_; ++k)
96+
int iMin = std::max(idx - radius_, range.start);
97+
int iMax = std::min(idx + radius_, range.end);
98+
for (int k = iMin; k <= iMax; ++k)
9799
{
98100
const Mat &neighbor = at(k, *frames_);
99101
float bRatio = at(idx, *blurrinessRates_) / at(k, *blurrinessRates_);

modules/videostab/src/motion_stabilizing.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ namespace videostab
5252
{
5353

5454
void MotionStabilizationPipeline::stabilize(
55-
int size, const std::vector<Mat> &motions, std::pair<int,int> range, Mat *stabilizationMotions)
55+
int size, const std::vector<Mat> &motions, const Range &range, Mat *stabilizationMotions)
5656
{
5757
std::vector<Mat> updatedMotions(motions.size());
5858
for (size_t i = 0; i < motions.size(); ++i)
@@ -81,7 +81,7 @@ void MotionStabilizationPipeline::stabilize(
8181

8282

8383
void MotionFilterBase::stabilize(
84-
int size, const std::vector<Mat> &motions, std::pair<int,int> range, Mat *stabilizationMotions)
84+
int size, const std::vector<Mat> &motions, const Range &range, Mat *stabilizationMotions)
8585
{
8686
for (int i = 0; i < size; ++i)
8787
stabilizationMotions[i] = stabilize(i, motions, range);
@@ -102,13 +102,13 @@ void GaussianMotionFilter::setParams(int _radius, float _stdev)
102102
}
103103

104104

105-
Mat GaussianMotionFilter::stabilize(int idx, const std::vector<Mat> &motions, std::pair<int,int> range)
105+
Mat GaussianMotionFilter::stabilize(int idx, const std::vector<Mat> &motions, const Range &range)
106106
{
107107
const Mat &cur = at(idx, motions);
108108
Mat res = Mat::zeros(cur.size(), cur.type());
109109
float sum = 0.f;
110-
int iMin = std::max(idx - radius_, range.first);
111-
int iMax = std::min(idx + radius_, range.second);
110+
int iMin = std::max(idx - radius_, range.start);
111+
int iMax = std::min(idx + radius_, range.end);
112112
for (int i = iMin; i <= iMax; ++i)
113113
{
114114
res += weight_[radius_ + i - idx] * getMotion(idx, i, motions);
@@ -132,15 +132,15 @@ LpMotionStabilizer::LpMotionStabilizer(MotionModel model)
132132

133133
#ifndef HAVE_CLP
134134

135-
void LpMotionStabilizer::stabilize(int, const std::vector<Mat>&, std::pair<int,int>, Mat*)
135+
void LpMotionStabilizer::stabilize(int, const std::vector<Mat>&, const Range &, Mat*)
136136
{
137137
CV_Error(Error::StsError, "The library is built without Clp support");
138138
}
139139

140140
#else
141141

142142
void LpMotionStabilizer::stabilize(
143-
int size, const std::vector<Mat> &motions, std::pair<int,int> /*range*/, Mat *stabilizationMotions)
143+
int size, const std::vector<Mat> &motions, const Range &/*range*/, Mat *stabilizationMotions)
144144
{
145145
CV_Assert(model_ <= MM_AFFINE);
146146

modules/videostab/src/stabilizer.cpp

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -63,11 +63,11 @@ StabilizerBase::StabilizerBase()
6363
setTrimRatio(0);
6464
setCorrectionForInclusion(false);
6565
setBorderMode(BORDER_REPLICATE);
66-
curPos_ = 0;
66+
curPos_ = -1;
67+
curStabilizedPos_ = -1;
6768
doDeblurring_ = false;
6869
doInpainting_ = false;
6970
processingStartTime_ = 0;
70-
curStabilizedPos_ = 0;
7171
}
7272

7373

@@ -143,12 +143,10 @@ bool StabilizerBase::doOneIteration()
143143
log_->print(".");
144144
return true;
145145
}
146-
147-
if (curStabilizedPos_ < curPos_)
146+
else if (curStabilizedPos_ < curPos_)
148147
{
149148
curStabilizedPos_++;
150-
at(curStabilizedPos_ + radius_, frames_) = at(curPos_, frames_);
151-
at(curStabilizedPos_ + radius_ - 1, motions_) = Mat::eye(3, 3, CV_32F);
149+
at(curPos_, motions_) = Mat::eye(3, 3, CV_32F);
152150
stabilizeFrame();
153151

154152
log_->print(".");
@@ -201,7 +199,7 @@ void StabilizerBase::stabilizeFrame()
201199
if (doDeblurring_)
202200
{
203201
at(curStabilizedPos_, frames_).copyTo(preProcessedFrame_);
204-
deblurer_->deblur(curStabilizedPos_, preProcessedFrame_);
202+
deblurer_->deblur(curStabilizedPos_, preProcessedFrame_, Range(0, curPos_));
205203
}
206204
else
207205
preProcessedFrame_ = at(curStabilizedPos_, frames_);
@@ -301,7 +299,7 @@ Mat OnePassStabilizer::estimateMotion()
301299

302300
Mat OnePassStabilizer::estimateStabilizationMotion()
303301
{
304-
return motionFilter_->stabilize(curStabilizedPos_, motions_, std::make_pair(0, curPos_));
302+
return motionFilter_->stabilize(curStabilizedPos_, motions_, Range(0, curPos_));
305303
}
306304

307305

@@ -438,7 +436,7 @@ void TwoPassStabilizer::runPrePassIfNecessary()
438436

439437
stabilizationMotions_.resize(frameCount_);
440438
motionStabilizer_->stabilize(
441-
frameCount_, motions_, std::make_pair(0, frameCount_ - 1), &stabilizationMotions_[0]);
439+
frameCount_, motions_, Range(0, frameCount_ - 1), &stabilizationMotions_[0]);
442440

443441
elapsedTime = clock() - startTime;
444442
log_->print("motion stabilization time: %.3f sec\n",
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
// This file is part of OpenCV project.
2+
// It is subject to the license terms in the LICENSE file found in the top-level directory
3+
// of this distribution and at http://opencv.org/license.html.
4+
5+
#include "test_precomp.hpp"
6+
#include <opencv2/ts/cuda_test.hpp> // EXPECT_MAT_NEAR
7+
8+
namespace opencv_test { namespace {
9+
10+
using namespace ::cv::videostab;
11+
12+
class OneFrameTestSource : public IFrameSource
13+
{
14+
public:
15+
OneFrameTestSource(const Mat &frame)
16+
{
17+
frameNumber_ = 0;
18+
frame_ = frame;
19+
}
20+
21+
virtual void reset() CV_OVERRIDE
22+
{
23+
frameNumber_ = 0;
24+
}
25+
26+
virtual Mat nextFrame() CV_OVERRIDE
27+
{
28+
return (frameNumber_++ == 0) ? frame_ : Mat();
29+
}
30+
31+
private:
32+
int frameNumber_;
33+
Mat frame_;
34+
};
35+
36+
TEST(OnePassStabilizer, oneFrame)
37+
{
38+
Mat frame(2, 3, CV_8UC3);
39+
randu(frame, Scalar::all(0), Scalar::all(255));
40+
41+
OnePassStabilizer stabilizer;
42+
stabilizer.setRadius(10);
43+
stabilizer.setFrameSource(makePtr<OneFrameTestSource>(frame));
44+
45+
Mat stabilizedFrame = stabilizer.nextFrame();
46+
EXPECT_MAT_NEAR(frame, stabilizedFrame, 0);
47+
EXPECT_TRUE(stabilizer.nextFrame().empty());
48+
}
49+
50+
TEST(OnePassStabilizer, oneFrame_deblur)
51+
{
52+
Mat frame(2, 3, CV_8UC3);
53+
randu(frame, Scalar::all(0), Scalar::all(255));
54+
55+
OnePassStabilizer stabilizer;
56+
stabilizer.setRadius(1);
57+
stabilizer.setFrameSource(makePtr<OneFrameTestSource>(frame));
58+
59+
Ptr<WeightingDeblurer> deblurer = makePtr<WeightingDeblurer>();
60+
deblurer->setRadius(10);
61+
stabilizer.setDeblurer(deblurer);
62+
63+
Mat stabilizedFrame = stabilizer.nextFrame();
64+
EXPECT_MAT_NEAR(frame, stabilizedFrame, 0);
65+
EXPECT_TRUE(stabilizer.nextFrame().empty());
66+
}
67+
68+
TEST(TwoPassStabilizer, oneFrame)
69+
{
70+
Mat frame(2, 3, CV_8UC3);
71+
randu(frame, Scalar::all(0), Scalar::all(255));
72+
73+
TwoPassStabilizer stabilizer;
74+
stabilizer.setRadius(10);
75+
stabilizer.setFrameSource(makePtr<OneFrameTestSource>(frame));
76+
77+
Mat stabilizedFrame = stabilizer.nextFrame();
78+
EXPECT_MAT_NEAR(frame, stabilizedFrame, 0);
79+
EXPECT_TRUE(stabilizer.nextFrame().empty());
80+
}
81+
82+
}} // namespace

0 commit comments

Comments
 (0)