Home | History | Annotate | Download | only in src
      1 /*M///////////////////////////////////////////////////////////////////////////////////////
      2 //
      3 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
      4 //
      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.
      8 //
      9 //
     10 //                           License Agreement
     11 //                For Open Source Computer Vision Library
     12 //
     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.
     16 //
     17 // Redistribution and use in source and binary forms, with or without modification,
     18 // are permitted provided that the following conditions are met:
     19 //
     20 //   * Redistribution's of source code must retain the above copyright notice,
     21 //     this list of conditions and the following disclaimer.
     22 //
     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.
     26 //
     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.
     29 //
     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.
     40 //
     41 //M*/
     42 
     43 #include "precomp.hpp"
     44 #include "opencv2/videostab/stabilizer.hpp"
     45 #include "opencv2/videostab/ring_buffer.hpp"
     46 
     47 // for debug purposes
     48 #define SAVE_MOTIONS 0
     49 
     50 namespace cv
     51 {
     52 namespace videostab
     53 {
     54 
     55 StabilizerBase::StabilizerBase()
     56 {
     57     setLog(makePtr<LogToStdout>());
     58     setFrameSource(makePtr<NullFrameSource>());
     59     setMotionEstimator(makePtr<KeypointBasedMotionEstimator>(makePtr<MotionEstimatorRansacL2>()));
     60     setDeblurer(makePtr<NullDeblurer>());
     61     setInpainter(makePtr<NullInpainter>());
     62     setRadius(15);
     63     setTrimRatio(0);
     64     setCorrectionForInclusion(false);
     65     setBorderMode(BORDER_REPLICATE);
     66 }
     67 
     68 
     69 void StabilizerBase::reset()
     70 {
     71     frameSize_ = Size(0, 0);
     72     frameMask_ = Mat();
     73     curPos_ = -1;
     74     curStabilizedPos_ = -1;
     75     doDeblurring_ = false;
     76     preProcessedFrame_ = Mat();
     77     doInpainting_ = false;
     78     inpaintingMask_ = Mat();
     79     frames_.clear();
     80     motions_.clear();
     81     blurrinessRates_.clear();
     82     stabilizedFrames_.clear();
     83     stabilizedMasks_.clear();
     84     stabilizationMotions_.clear();
     85     processingStartTime_ = 0;
     86 }
     87 
     88 
     89 Mat StabilizerBase::nextStabilizedFrame()
     90 {
     91     // check if we've processed all frames already
     92     if (curStabilizedPos_ == curPos_ && curStabilizedPos_ != -1)
     93     {
     94         logProcessingTime();
     95         return Mat();
     96     }
     97 
     98     bool processed;
     99     do processed = doOneIteration();
    100     while (processed && curStabilizedPos_ == -1);
    101 
    102     // check if the frame source is empty
    103     if (curStabilizedPos_ == -1)
    104     {
    105         logProcessingTime();
    106         return Mat();
    107     }
    108 
    109     return postProcessFrame(at(curStabilizedPos_, stabilizedFrames_));
    110 }
    111 
    112 
    113 bool StabilizerBase::doOneIteration()
    114 {
    115     Mat frame = frameSource_->nextFrame();
    116     if (!frame.empty())
    117     {
    118         curPos_++;
    119 
    120         if (curPos_ > 0)
    121         {
    122             at(curPos_, frames_) = frame;
    123 
    124             if (doDeblurring_)
    125                 at(curPos_, blurrinessRates_) = calcBlurriness(frame);
    126 
    127             at(curPos_ - 1, motions_) = estimateMotion();
    128 
    129             if (curPos_ >= radius_)
    130             {
    131                 curStabilizedPos_ = curPos_ - radius_;
    132                 stabilizeFrame();
    133             }
    134         }
    135         else
    136             setUp(frame);
    137 
    138         log_->print(".");
    139         return true;
    140     }
    141 
    142     if (curStabilizedPos_ < curPos_)
    143     {
    144         curStabilizedPos_++;
    145         at(curStabilizedPos_ + radius_, frames_) = at(curPos_, frames_);
    146         at(curStabilizedPos_ + radius_ - 1, motions_) = Mat::eye(3, 3, CV_32F);
    147         stabilizeFrame();
    148 
    149         log_->print(".");
    150         return true;
    151     }
    152 
    153     return false;
    154 }
    155 
    156 
    157 void StabilizerBase::setUp(const Mat &firstFrame)
    158 {
    159     InpainterBase *inpaint = inpainter_.get();
    160     doInpainting_ = dynamic_cast<NullInpainter*>(inpaint) == 0;
    161     if (doInpainting_)
    162     {
    163         inpainter_->setMotionModel(motionEstimator_->motionModel());
    164         inpainter_->setFrames(frames_);
    165         inpainter_->setMotions(motions_);
    166         inpainter_->setStabilizedFrames(stabilizedFrames_);
    167         inpainter_->setStabilizationMotions(stabilizationMotions_);
    168     }
    169 
    170     DeblurerBase *deblurer = deblurer_.get();
    171     doDeblurring_ = dynamic_cast<NullDeblurer*>(deblurer) == 0;
    172     if (doDeblurring_)
    173     {
    174         blurrinessRates_.resize(2*radius_ + 1);
    175         float blurriness = calcBlurriness(firstFrame);
    176         for (int i  = -radius_; i <= 0; ++i)
    177             at(i, blurrinessRates_) = blurriness;
    178         deblurer_->setFrames(frames_);
    179         deblurer_->setMotions(motions_);
    180         deblurer_->setBlurrinessRates(blurrinessRates_);
    181     }
    182 
    183     log_->print("processing frames");
    184     processingStartTime_ = clock();
    185 }
    186 
    187 
    188 void StabilizerBase::stabilizeFrame()
    189 {
    190     Mat stabilizationMotion = estimateStabilizationMotion();
    191     if (doCorrectionForInclusion_)
    192         stabilizationMotion = ensureInclusionConstraint(stabilizationMotion, frameSize_, trimRatio_);
    193 
    194     at(curStabilizedPos_, stabilizationMotions_) = stabilizationMotion;
    195 
    196     if (doDeblurring_)
    197     {
    198         at(curStabilizedPos_, frames_).copyTo(preProcessedFrame_);
    199         deblurer_->deblur(curStabilizedPos_, preProcessedFrame_);
    200     }
    201     else
    202         preProcessedFrame_ = at(curStabilizedPos_, frames_);
    203 
    204     // apply stabilization transformation
    205 
    206     if (motionEstimator_->motionModel() != MM_HOMOGRAPHY)
    207         warpAffine(
    208                 preProcessedFrame_, at(curStabilizedPos_, stabilizedFrames_),
    209                 stabilizationMotion(Rect(0,0,3,2)), frameSize_, INTER_LINEAR, borderMode_);
    210     else
    211         warpPerspective(
    212                 preProcessedFrame_, at(curStabilizedPos_, stabilizedFrames_),
    213                 stabilizationMotion, frameSize_, INTER_LINEAR, borderMode_);
    214 
    215     if (doInpainting_)
    216     {
    217         if (motionEstimator_->motionModel() != MM_HOMOGRAPHY)
    218             warpAffine(
    219                     frameMask_, at(curStabilizedPos_, stabilizedMasks_),
    220                     stabilizationMotion(Rect(0,0,3,2)), frameSize_, INTER_NEAREST);
    221         else
    222             warpPerspective(
    223                     frameMask_, at(curStabilizedPos_, stabilizedMasks_),
    224                     stabilizationMotion, frameSize_, INTER_NEAREST);
    225 
    226         erode(at(curStabilizedPos_, stabilizedMasks_), at(curStabilizedPos_, stabilizedMasks_),
    227               Mat());
    228 
    229         at(curStabilizedPos_, stabilizedMasks_).copyTo(inpaintingMask_);
    230 
    231         inpainter_->inpaint(
    232             curStabilizedPos_, at(curStabilizedPos_, stabilizedFrames_), inpaintingMask_);
    233     }
    234 }
    235 
    236 
    237 Mat StabilizerBase::postProcessFrame(const Mat &frame)
    238 {
    239     // trim frame
    240     int dx = static_cast<int>(floor(trimRatio_ * frame.cols));
    241     int dy = static_cast<int>(floor(trimRatio_ * frame.rows));
    242     return frame(Rect(dx, dy, frame.cols - 2*dx, frame.rows - 2*dy));
    243 }
    244 
    245 
    246 void StabilizerBase::logProcessingTime()
    247 {
    248     clock_t elapsedTime = clock() - processingStartTime_;
    249     log_->print("\nprocessing time: %.3f sec\n", static_cast<double>(elapsedTime) / CLOCKS_PER_SEC);
    250 }
    251 
    252 
    253 OnePassStabilizer::OnePassStabilizer()
    254 {
    255     setMotionFilter(makePtr<GaussianMotionFilter>());
    256     reset();
    257 }
    258 
    259 
    260 void OnePassStabilizer::reset()
    261 {
    262     StabilizerBase::reset();
    263 }
    264 
    265 
    266 void OnePassStabilizer::setUp(const Mat &firstFrame)
    267 {
    268     frameSize_ = firstFrame.size();
    269     frameMask_.create(frameSize_, CV_8U);
    270     frameMask_.setTo(255);
    271 
    272     int cacheSize = 2*radius_ + 1;
    273     frames_.resize(cacheSize);
    274     stabilizedFrames_.resize(cacheSize);
    275     stabilizedMasks_.resize(cacheSize);
    276     motions_.resize(cacheSize);
    277     stabilizationMotions_.resize(cacheSize);
    278 
    279     for (int i = -radius_; i < 0; ++i)
    280     {
    281         at(i, motions_) = Mat::eye(3, 3, CV_32F);
    282         at(i, frames_) = firstFrame;
    283     }
    284 
    285     at(0, frames_) = firstFrame;
    286 
    287     StabilizerBase::setUp(firstFrame);
    288 }
    289 
    290 
    291 Mat OnePassStabilizer::estimateMotion()
    292 {
    293     return motionEstimator_->estimate(at(curPos_ - 1, frames_), at(curPos_, frames_));
    294 }
    295 
    296 
    297 Mat OnePassStabilizer::estimateStabilizationMotion()
    298 {
    299     return motionFilter_->stabilize(curStabilizedPos_, motions_, std::make_pair(0, curPos_));
    300 }
    301 
    302 
    303 Mat OnePassStabilizer::postProcessFrame(const Mat &frame)
    304 {
    305     return StabilizerBase::postProcessFrame(frame);
    306 }
    307 
    308 
    309 TwoPassStabilizer::TwoPassStabilizer()
    310 {
    311     setMotionStabilizer(makePtr<GaussianMotionFilter>());
    312     setWobbleSuppressor(makePtr<NullWobbleSuppressor>());
    313     setEstimateTrimRatio(false);
    314     reset();
    315 }
    316 
    317 
    318 void TwoPassStabilizer::reset()
    319 {
    320     StabilizerBase::reset();
    321     frameCount_ = 0;
    322     isPrePassDone_ = false;
    323     doWobbleSuppression_ = false;
    324     motions2_.clear();
    325     suppressedFrame_ = Mat();
    326 }
    327 
    328 
    329 Mat TwoPassStabilizer::nextFrame()
    330 {
    331     runPrePassIfNecessary();
    332     return StabilizerBase::nextStabilizedFrame();
    333 }
    334 
    335 
    336 #if SAVE_MOTIONS
    337 static void saveMotions(
    338         int frameCount, const std::vector<Mat> &motions, const std::vector<Mat> &stabilizationMotions)
    339 {
    340     std::ofstream fm("log_motions.csv");
    341     for (int i = 0; i < frameCount - 1; ++i)
    342     {
    343         Mat_<float> M = at(i, motions);
    344         fm << M(0,0) << " " << M(0,1) << " " << M(0,2) << " "
    345            << M(1,0) << " " << M(1,1) << " " << M(1,2) << " "
    346            << M(2,0) << " " << M(2,1) << " " << M(2,2) << std::endl;
    347     }
    348     std::ofstream fo("log_orig.csv");
    349     for (int i = 0; i < frameCount; ++i)
    350     {
    351         Mat_<float> M = getMotion(0, i, motions);
    352         fo << M(0,0) << " " << M(0,1) << " " << M(0,2) << " "
    353            << M(1,0) << " " << M(1,1) << " " << M(1,2) << " "
    354            << M(2,0) << " " << M(2,1) << " " << M(2,2) << std::endl;
    355     }
    356     std::ofstream fs("log_stab.csv");
    357     for (int i = 0; i < frameCount; ++i)
    358     {
    359         Mat_<float> M = stabilizationMotions[i] * getMotion(0, i, motions);
    360         fs << M(0,0) << " " << M(0,1) << " " << M(0,2) << " "
    361            << M(1,0) << " " << M(1,1) << " " << M(1,2) << " "
    362            << M(2,0) << " " << M(2,1) << " " << M(2,2) << std::endl;
    363     }
    364 }
    365 #endif
    366 
    367 
    368 void TwoPassStabilizer::runPrePassIfNecessary()
    369 {
    370     if (!isPrePassDone_)
    371     {
    372         // check if we must do wobble suppression
    373 
    374         WobbleSuppressorBase *wobble = wobbleSuppressor_.get();
    375         doWobbleSuppression_ = dynamic_cast<NullWobbleSuppressor*>(wobble) == 0;
    376 
    377         // estimate motions
    378 
    379         clock_t startTime = clock();
    380         log_->print("first pass: estimating motions");
    381 
    382         Mat prevFrame, frame;
    383         bool ok = true, ok2 = true;
    384 
    385         while (!(frame = frameSource_->nextFrame()).empty())
    386         {
    387             if (frameCount_ > 0)
    388             {
    389                 motions_.push_back(motionEstimator_->estimate(prevFrame, frame, &ok));
    390 
    391                 if (doWobbleSuppression_)
    392                 {
    393                     Mat M = wobbleSuppressor_->motionEstimator()->estimate(prevFrame, frame, &ok2);
    394                     if (ok2)
    395                         motions2_.push_back(M);
    396                     else
    397                         motions2_.push_back(motions_.back());
    398                 }
    399 
    400                 if (ok)
    401                 {
    402                     if (ok2) log_->print(".");
    403                     else log_->print("?");
    404                 }
    405                 else log_->print("x");
    406             }
    407             else
    408             {
    409                 frameSize_ = frame.size();
    410                 frameMask_.create(frameSize_, CV_8U);
    411                 frameMask_.setTo(255);
    412             }
    413 
    414             prevFrame = frame;
    415             frameCount_++;
    416         }
    417 
    418         clock_t elapsedTime = clock() - startTime;
    419         log_->print("\nmotion estimation time: %.3f sec\n",
    420                     static_cast<double>(elapsedTime) / CLOCKS_PER_SEC);
    421 
    422         // add aux. motions
    423 
    424         for (int i = 0; i < radius_; ++i)
    425             motions_.push_back(Mat::eye(3, 3, CV_32F));
    426 
    427         // stabilize
    428 
    429         startTime = clock();
    430 
    431         stabilizationMotions_.resize(frameCount_);
    432         motionStabilizer_->stabilize(
    433             frameCount_, motions_, std::make_pair(0, frameCount_ - 1), &stabilizationMotions_[0]);
    434 
    435         elapsedTime = clock() - startTime;
    436         log_->print("motion stabilization time: %.3f sec\n",
    437                     static_cast<double>(elapsedTime) / CLOCKS_PER_SEC);
    438 
    439         // estimate optimal trim ratio if necessary
    440 
    441         if (mustEstTrimRatio_)
    442         {
    443             trimRatio_ = 0;
    444             for (int i = 0; i < frameCount_; ++i)
    445             {
    446                 Mat S = stabilizationMotions_[i];
    447                 trimRatio_ = std::max(trimRatio_, estimateOptimalTrimRatio(S, frameSize_));
    448             }
    449             log_->print("estimated trim ratio: %f\n", static_cast<double>(trimRatio_));
    450         }
    451 
    452 #if SAVE_MOTIONS
    453         saveMotions(frameCount_, motions_, stabilizationMotions_);
    454 #endif
    455 
    456         isPrePassDone_ = true;
    457         frameSource_->reset();
    458     }
    459 }
    460 
    461 
    462 void TwoPassStabilizer::setUp(const Mat &firstFrame)
    463 {
    464     int cacheSize = 2*radius_ + 1;
    465     frames_.resize(cacheSize);
    466     stabilizedFrames_.resize(cacheSize);
    467     stabilizedMasks_.resize(cacheSize);
    468 
    469     for (int i = -radius_; i <= 0; ++i)
    470         at(i, frames_) = firstFrame;
    471 
    472     WobbleSuppressorBase *wobble = wobbleSuppressor_.get();
    473     doWobbleSuppression_ = dynamic_cast<NullWobbleSuppressor*>(wobble) == 0;
    474     if (doWobbleSuppression_)
    475     {
    476         wobbleSuppressor_->setFrameCount(frameCount_);
    477         wobbleSuppressor_->setMotions(motions_);
    478         wobbleSuppressor_->setMotions2(motions2_);
    479         wobbleSuppressor_->setStabilizationMotions(stabilizationMotions_);
    480     }
    481 
    482     StabilizerBase::setUp(firstFrame);
    483 }
    484 
    485 
    486 Mat TwoPassStabilizer::estimateMotion()
    487 {
    488     return motions_[curPos_ - 1].clone();
    489 }
    490 
    491 
    492 Mat TwoPassStabilizer::estimateStabilizationMotion()
    493 {
    494     return stabilizationMotions_[curStabilizedPos_].clone();
    495 }
    496 
    497 
    498 Mat TwoPassStabilizer::postProcessFrame(const Mat &frame)
    499 {
    500     wobbleSuppressor_->suppress(curStabilizedPos_, frame, suppressedFrame_);
    501     return StabilizerBase::postProcessFrame(suppressedFrame_);
    502 }
    503 
    504 } // namespace videostab
    505 } // namespace cv
    506