1 /*M///////////////////////////////////////////////////////////////////////////////////////
3 // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
5 // By downloading, copying, installing or using the software you agree to this license.
6 // If you do not agree to this license, do not download, install,
7 // copy or use the software.
11 // For Open Source Computer Vision Library
13 // Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
14 // Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved.
15 // Third party copyrights are property of their respective owners.
17 // Redistribution and use in source and binary forms, with or without modification,
18 // are permitted provided that the following conditions are met:
20 // * Redistribution's of source code must retain the above copyright notice,
21 // this list of conditions and the following disclaimer.
23 // * Redistribution's in binary form must reproduce the above copyright notice,
24 // this list of conditions and the following disclaimer in the documentation
25 // and/or other materials provided with the distribution.
27 // * The name of the copyright holders may not be used to endorse or promote products
28 // derived from this software without specific prior written permission.
30 // This software is provided by the copyright holders and contributors "as is" and
31 // any express or implied warranties, including, but not limited to, the implied
32 // warranties of merchantability and fitness for a particular purpose are disclaimed.
33 // In no event shall the Intel Corporation or contributors be liable for any direct,
34 // indirect, incidental, special, exemplary, or consequential damages
35 // (including, but not limited to, procurement of substitute goods or services;
36 // loss of use, data, or profits; or business interruption) however caused
37 // and on any theory of liability, whether in contract, strict liability,
38 // or tort (including negligence or otherwise) arising in any way out of
39 // the use of this software, even if advised of the possibility of such damage.
43 #include "precomp.hpp"
44 #include "opencv2/videostab/stabilizer.hpp"
45 #include "opencv2/videostab/ring_buffer.hpp"
54 StabilizerBase::StabilizerBase()
56 setLog(new NullLog());
57 setFrameSource(new NullFrameSource());
58 setMotionEstimator(new PyrLkRobustMotionEstimator());
59 setDeblurer(new NullDeblurer());
60 setInpainter(new NullInpainter());
63 setCorrectionForInclusion(false);
64 setBorderMode(BORDER_REPLICATE);
68 void StabilizerBase::reset()
70 frameSize_ = Size(0, 0);
73 curStabilizedPos_ = -1;
74 doDeblurring_ = false;
75 preProcessedFrame_ = Mat();
76 doInpainting_ = false;
77 inpaintingMask_ = Mat();
80 blurrinessRates_.clear();
81 stabilizedFrames_.clear();
82 stabilizedMasks_.clear();
83 stabilizationMotions_.clear();
87 Mat StabilizerBase::nextStabilizedFrame()
89 // check if we've processed all frames already
90 if (curStabilizedPos_ == curPos_ && curStabilizedPos_ != -1)
94 do processed = doOneIteration();
95 while (processed && curStabilizedPos_ == -1);
97 // check if frame source is empty
98 if (curStabilizedPos_ == -1)
101 return postProcessFrame(at(curStabilizedPos_, stabilizedFrames_));
105 bool StabilizerBase::doOneIteration()
107 Mat frame = frameSource_->nextFrame();
114 at(curPos_, frames_) = frame;
117 at(curPos_, blurrinessRates_) = calcBlurriness(frame);
119 at(curPos_ - 1, motions_) = estimateMotion();
121 if (curPos_ >= radius_)
123 curStabilizedPos_ = curPos_ - radius_;
134 if (curStabilizedPos_ < curPos_)
137 at(curStabilizedPos_ + radius_, frames_) = at(curPos_, frames_);
138 at(curStabilizedPos_ + radius_ - 1, motions_) = Mat::eye(3, 3, CV_32F);
149 void StabilizerBase::setUp(const Mat &firstFrame)
151 InpainterBase *inpainter = static_cast<InpainterBase*>(inpainter_);
152 doInpainting_ = dynamic_cast<NullInpainter*>(inpainter) == 0;
155 inpainter_->setMotionModel(motionEstimator_->motionModel());
156 inpainter_->setFrames(frames_);
157 inpainter_->setMotions(motions_);
158 inpainter_->setStabilizedFrames(stabilizedFrames_);
159 inpainter_->setStabilizationMotions(stabilizationMotions_);
162 DeblurerBase *deblurer = static_cast<DeblurerBase*>(deblurer_);
163 doDeblurring_ = dynamic_cast<NullDeblurer*>(deblurer) == 0;
166 blurrinessRates_.resize(2*radius_ + 1);
167 float blurriness = calcBlurriness(firstFrame);
168 for (int i = -radius_; i <= 0; ++i)
169 at(i, blurrinessRates_) = blurriness;
170 deblurer_->setFrames(frames_);
171 deblurer_->setMotions(motions_);
172 deblurer_->setBlurrinessRates(blurrinessRates_);
175 log_->print("processing frames");
179 void StabilizerBase::stabilizeFrame()
181 Mat stabilizationMotion = estimateStabilizationMotion();
182 if (doCorrectionForInclusion_)
183 stabilizationMotion = ensureInclusionConstraint(stabilizationMotion, frameSize_, trimRatio_);
185 at(curStabilizedPos_, stabilizationMotions_) = stabilizationMotion;
189 at(curStabilizedPos_, frames_).copyTo(preProcessedFrame_);
190 deblurer_->deblur(curStabilizedPos_, preProcessedFrame_);
193 preProcessedFrame_ = at(curStabilizedPos_, frames_);
195 // apply stabilization transformation
197 if (motionEstimator_->motionModel() != HOMOGRAPHY)
199 preProcessedFrame_, at(curStabilizedPos_, stabilizedFrames_),
200 stabilizationMotion(Rect(0,0,3,2)), frameSize_, INTER_LINEAR, borderMode_);
203 preProcessedFrame_, at(curStabilizedPos_, stabilizedFrames_),
204 stabilizationMotion, frameSize_, INTER_LINEAR, borderMode_);
208 if (motionEstimator_->motionModel() != HOMOGRAPHY)
210 frameMask_, at(curStabilizedPos_, stabilizedMasks_),
211 stabilizationMotion(Rect(0,0,3,2)), frameSize_, INTER_NEAREST);
214 frameMask_, at(curStabilizedPos_, stabilizedMasks_),
215 stabilizationMotion, frameSize_, INTER_NEAREST);
217 erode(at(curStabilizedPos_, stabilizedMasks_), at(curStabilizedPos_, stabilizedMasks_),
220 at(curStabilizedPos_, stabilizedMasks_).copyTo(inpaintingMask_);
223 curStabilizedPos_, at(curStabilizedPos_, stabilizedFrames_), inpaintingMask_);
228 Mat StabilizerBase::postProcessFrame(const Mat &frame)
231 int dx = static_cast<int>(floor(trimRatio_ * frame.cols));
232 int dy = static_cast<int>(floor(trimRatio_ * frame.rows));
233 return frame(Rect(dx, dy, frame.cols - 2*dx, frame.rows - 2*dy));
237 OnePassStabilizer::OnePassStabilizer()
239 setMotionFilter(new GaussianMotionFilter());
244 void OnePassStabilizer::reset()
246 StabilizerBase::reset();
250 void OnePassStabilizer::setUp(const Mat &firstFrame)
252 frameSize_ = firstFrame.size();
253 frameMask_.create(frameSize_, CV_8U);
254 frameMask_.setTo(255);
256 int cacheSize = 2*radius_ + 1;
257 frames_.resize(cacheSize);
258 stabilizedFrames_.resize(cacheSize);
259 stabilizedMasks_.resize(cacheSize);
260 motions_.resize(cacheSize);
261 stabilizationMotions_.resize(cacheSize);
263 for (int i = -radius_; i < 0; ++i)
265 at(i, motions_) = Mat::eye(3, 3, CV_32F);
266 at(i, frames_) = firstFrame;
269 at(0, frames_) = firstFrame;
271 StabilizerBase::setUp(firstFrame);
275 Mat OnePassStabilizer::estimateMotion()
277 return motionEstimator_->estimate(at(curPos_ - 1, frames_), at(curPos_, frames_));
281 Mat OnePassStabilizer::estimateStabilizationMotion()
283 return motionFilter_->stabilize(curStabilizedPos_, motions_, make_pair(0, curPos_));
287 Mat OnePassStabilizer::postProcessFrame(const Mat &frame)
289 return StabilizerBase::postProcessFrame(frame);
293 TwoPassStabilizer::TwoPassStabilizer()
295 setMotionStabilizer(new GaussianMotionFilter());
296 setWobbleSuppressor(new NullWobbleSuppressor());
297 setEstimateTrimRatio(false);
302 void TwoPassStabilizer::reset()
304 StabilizerBase::reset();
306 isPrePassDone_ = false;
307 suppressedFrame_ = Mat();
311 Mat TwoPassStabilizer::nextFrame()
313 runPrePassIfNecessary();
314 return StabilizerBase::nextStabilizedFrame();
318 vector<Mat> TwoPassStabilizer::motions() const
320 if (frameCount_ == 0)
321 return vector<Mat>();
322 vector<Mat> res(frameCount_ - 1);
323 copy(motions_.begin(), motions_.begin() + frameCount_ - 1, res.begin());
328 void TwoPassStabilizer::runPrePassIfNecessary()
332 log_->print("first pass: estimating motions");
334 Mat prevFrame, frame;
336 while (!(frame = frameSource_->nextFrame()).empty())
339 motions_.push_back(motionEstimator_->estimate(prevFrame, frame));
342 frameSize_ = frame.size();
343 frameMask_.create(frameSize_, CV_8U);
344 frameMask_.setTo(255);
353 for (int i = 0; i < radius_; ++i)
354 motions_.push_back(Mat::eye(3, 3, CV_32F));
357 stabilizationMotions_.resize(frameCount_);
359 motionStabilizer_->stabilize(
360 frameCount_, motions_, make_pair(0, frameCount_ - 1), &stabilizationMotions_[0]);
362 if (mustEstTrimRatio_)
365 for (int i = 0; i < frameCount_; ++i)
367 Mat S = stabilizationMotions_[i];
368 trimRatio_ = std::max(trimRatio_, estimateOptimalTrimRatio(S, frameSize_));
370 log_->print("estimated trim ratio: %f\n", static_cast<double>(trimRatio_));
373 isPrePassDone_ = true;
374 frameSource_->reset();
379 void TwoPassStabilizer::setUp(const Mat &firstFrame)
381 int cacheSize = 2*radius_ + 1;
382 frames_.resize(cacheSize);
383 stabilizedFrames_.resize(cacheSize);
384 stabilizedMasks_.resize(cacheSize);
386 for (int i = -radius_; i <= 0; ++i)
387 at(i, frames_) = firstFrame;
389 wobbleSuppressor_->setFrames(frames_);
390 wobbleSuppressor_->setMotions(motions_);
391 wobbleSuppressor_->setStabilizedFrames(stabilizedFrames_);
392 wobbleSuppressor_->setStabilizationMotions(stabilizationMotions_);
394 StabilizerBase::setUp(firstFrame);
398 Mat TwoPassStabilizer::estimateMotion()
400 return motions_[curPos_ - 1].clone();
404 Mat TwoPassStabilizer::estimateStabilizationMotion()
406 return stabilizationMotions_[curStabilizedPos_].clone();
410 Mat TwoPassStabilizer::postProcessFrame(const Mat &/*frame*/)
412 wobbleSuppressor_->suppress(curStabilizedPos_, suppressedFrame_);
413 return StabilizerBase::postProcessFrame(suppressedFrame_);
416 } // namespace videostab