/* * stablizer.cpp - abstract for DVS (Digital Video Stabilizer) * * Copyright (c) 2014-2016 Intel Corporation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Author: Zong Wei */ #include "stabilizer.h" using namespace cv; using namespace cv::videostab; using namespace std; Mat OnePassVideoStabilizer::nextStabilizedMotion(DvsData* frame, int& stablizedPos) { if (!(frame->data.empty())) { Mat image; frame->data.getMat(ACCESS_READ).copyTo(image); curPos_++; if (curPos_ > 0) { at(curPos_, frames_) = image; if (doDeblurring_) at(curPos_, blurrinessRates_) = calcBlurriness(image); at(curPos_ - 1, motions_) = estimateMotion(); if (curPos_ >= radius_) { curStabilizedPos_ = curPos_ - radius_; Mat stabilizationMotion = estimateStabilizationMotion(); if (doCorrectionForInclusion_) stabilizationMotion = ensureInclusionConstraint(stabilizationMotion, frameSize_, trimRatio_); at(curStabilizedPos_, stabilizationMotions_) = stabilizationMotion; stablizedPos = curStabilizedPos_; return stabilizationMotion; } } else setUpFrame(image); log_->print("."); return Mat(); } if (curStabilizedPos_ < curPos_) { curStabilizedPos_++; stablizedPos = curStabilizedPos_; at(curStabilizedPos_ + radius_, frames_) = at(curPos_, frames_); at(curStabilizedPos_ + radius_ - 1, motions_) = Mat::eye(3, 3, CV_32F); Mat stabilizationMotion = estimateStabilizationMotion(); if (doCorrectionForInclusion_) stabilizationMotion = ensureInclusionConstraint(stabilizationMotion, frameSize_, trimRatio_); at(curStabilizedPos_, stabilizationMotions_) = stabilizationMotion; log_->print("."); return stabilizationMotion; } return Mat(); } Mat OnePassVideoStabilizer::estimateMotion() { #if ENABLE_DVS_CL_PATH cv::UMat frame0 = at(curPos_ - 1, frames_).getUMat(ACCESS_READ); cv::UMat frame1 = at(curPos_, frames_).getUMat(ACCESS_READ); cv::UMat ugrayImage0; cv::UMat ugrayImage1; if ( frame0.type() != CV_8U ) { cvtColor( frame0, ugrayImage0, COLOR_BGR2GRAY ); } else { ugrayImage0 = frame0; } if ( frame1.type() != CV_8U ) { cvtColor( frame1, ugrayImage1, COLOR_BGR2GRAY ); } else { ugrayImage1 = frame1; } return motionEstimator_.dynamicCast()->estimate(ugrayImage0, ugrayImage1); #else return motionEstimator_.dynamicCast()->estimate(at(curPos_ - 1, frames_), at(curPos_, frames_)); #endif } void OnePassVideoStabilizer::setUpFrame(const Mat &firstFrame) { frameSize_ = firstFrame.size(); frameMask_.create(frameSize_, CV_8U); frameMask_.setTo(255); int cacheSize = 2 * radius_ + 1; frames_.resize(2); motions_.resize(cacheSize); stabilizationMotions_.resize(cacheSize); for (int i = -radius_; i < 0; ++i) { at(i, motions_) = Mat::eye(3, 3, CV_32F); at(i, frames_) = firstFrame; } at(0, frames_) = firstFrame; StabilizerBase::setUp(firstFrame); } Mat TwoPassVideoStabilizer::nextStabilizedMotion(DvsData* frame, int& stablizedPos) { if (!(frame->data.empty())) { Mat image; frame->data.getMat(ACCESS_READ).copyTo(image); curPos_++; if (curPos_ > 0) { at(curPos_, frames_) = image; if (doDeblurring_) at(curPos_, blurrinessRates_) = calcBlurriness(image); at(curPos_ - 1, motions_) = estimateMotion(); if (curPos_ >= radius_) { curStabilizedPos_ = curPos_ - radius_; Mat stabilizationMotion = estimateStabilizationMotion(); if (doCorrectionForInclusion_) stabilizationMotion = ensureInclusionConstraint(stabilizationMotion, frameSize_, trimRatio_); at(curStabilizedPos_, stabilizationMotions_) = stabilizationMotion; stablizedPos = curStabilizedPos_; return stabilizationMotion; } } else setUpFrame(image); log_->print("."); return Mat(); } if (curStabilizedPos_ < curPos_) { curStabilizedPos_++; stablizedPos = curStabilizedPos_; at(curStabilizedPos_ + radius_, frames_) = at(curPos_, frames_); at(curStabilizedPos_ + radius_ - 1, motions_) = Mat::eye(3, 3, CV_32F); Mat stabilizationMotion = estimateStabilizationMotion(); if (doCorrectionForInclusion_) stabilizationMotion = ensureInclusionConstraint(stabilizationMotion, frameSize_, trimRatio_); at(curStabilizedPos_, stabilizationMotions_) = stabilizationMotion; log_->print("."); return stabilizationMotion; } return Mat(); } Mat TwoPassVideoStabilizer::estimateMotion() { #if ENABLE_DVS_CL_PATH cv::UMat frame0 = at(curPos_ - 1, frames_).getUMat(ACCESS_READ); cv::UMat frame1 = at(curPos_, frames_).getUMat(ACCESS_READ); cv::UMat ugrayImage0; cv::UMat ugrayImage1; if ( frame0.type() != CV_8U ) { cvtColor( frame0, ugrayImage0, COLOR_BGR2GRAY ); } else { ugrayImage0 = frame0; } if ( frame1.type() != CV_8U ) { cvtColor( frame1, ugrayImage1, COLOR_BGR2GRAY ); } else { ugrayImage1 = frame1; } return motionEstimator_.dynamicCast()->estimate(ugrayImage0, ugrayImage1); #else return motionEstimator_.dynamicCast()->estimate(at(curPos_ - 1, frames_), at(curPos_, frames_)); #endif } void TwoPassVideoStabilizer::setUpFrame(const Mat &firstFrame) { //int cacheSize = 2*radius_ + 1; frames_.resize(2); stabilizedFrames_.resize(2); stabilizedMasks_.resize(2); for (int i = -1; i <= 0; ++i) at(i, frames_) = firstFrame; StabilizerBase::setUp(firstFrame); } VideoStabilizer::VideoStabilizer( bool isTwoPass, bool wobbleSuppress, bool deblur, bool inpainter) : isTwoPass_ (isTwoPass) , trimRatio_ (0.05f) { Ptr est = makePtr(MM_HOMOGRAPHY); Ptr outlierRejector = makePtr(); Ptr kbest = makePtr(est); kbest->setDetector(GFTTDetector::create(1000, 0.01, 15)); kbest->setOutlierRejector(outlierRejector); if (isTwoPass) { Ptr twoPassStabilizer = makePtr(); stabilizer_ = twoPassStabilizer; twoPassStabilizer->setEstimateTrimRatio(false); twoPassStabilizer->setMotionStabilizer(makePtr(15, 10)); if (wobbleSuppress) { Ptr ws = makePtr(); ws->setMotionEstimator(kbest); ws->setPeriod(30); twoPassStabilizer->setWobbleSuppressor(ws); } } else { Ptr onePassStabilizer = makePtr(); stabilizer_ = onePassStabilizer; onePassStabilizer->setMotionFilter(makePtr(15, 10)); } stabilizer_->setMotionEstimator(kbest); stabilizer_->setRadius(15); if (deblur) { Ptr deblurrer = makePtr(); deblurrer->setRadius(3); deblurrer->setSensitivity(0.001f); stabilizer_->setDeblurer(deblurrer); } if (inpainter) { bool inpaintMosaic = true; bool inpaintColorAverage = true; bool inpaintColorNs = false; bool inpaintColorTelea = false; // init inpainter InpaintingPipeline *inpainters = new InpaintingPipeline(); Ptr inpainters_(inpainters); if (true == inpaintMosaic) { Ptr inp = makePtr(); inp->setStdevThresh(10.0f); inpainters->pushBack(inp); } if (true == inpaintColorAverage) inpainters->pushBack(makePtr()); else if (true == inpaintColorNs) inpainters->pushBack(makePtr(0, 2)); else if (true == inpaintColorTelea) inpainters->pushBack(makePtr(1, 2)); if (!inpainters->empty()) { inpainters->setRadius(2); stabilizer_->setInpainter(inpainters_); } } } VideoStabilizer::~VideoStabilizer() {} void VideoStabilizer::configFeatureDetector(int features, double minDistance) { Ptr estimator = stabilizer_->motionEstimator(); Ptr detector = estimator.dynamicCast()->detector(); if (NULL == detector) { return; } detector.dynamicCast()->setMaxFeatures(features); detector.dynamicCast()->setMinDistance(minDistance); } void VideoStabilizer::configMotionFilter(int radius, float stdev) { if (isTwoPass_) { Ptr stab = stabilizer_.dynamicCast(); Ptr motionStabilizer = stab->motionStabilizer(); motionStabilizer.dynamicCast()->setParams(radius, stdev); } else { Ptr stab = stabilizer_.dynamicCast(); Ptr motionFilter = stab->motionFilter(); motionFilter.dynamicCast()->setParams(radius, stdev); } stabilizer_->setRadius(radius); } void VideoStabilizer::configDeblurrer(int radius, double sensitivity) { Ptr deblurrer = stabilizer_->deblurrer(); if (NULL == deblurrer) { return; } deblurrer->setRadius(radius); deblurrer.dynamicCast()->setSensitivity(sensitivity); } void VideoStabilizer::setFrameSize(Size frameSize) { frameSize_ = frameSize; } Mat VideoStabilizer::nextFrame() { if (isTwoPass_) { Ptr stab = stabilizer_.dynamicCast(); return stab->nextFrame(); } else { Ptr stab = stabilizer_.dynamicCast(); return stab->nextFrame(); } } Mat VideoStabilizer::nextStabilizedMotion(DvsData* frame, int& stablizedPos) { Mat HMatrix; if (isTwoPass_) { Ptr stab = stabilizer_.dynamicCast(); HMatrix = stab->nextStabilizedMotion(frame, stablizedPos); } else { Ptr stab = stabilizer_.dynamicCast(); HMatrix = stab->nextStabilizedMotion(frame, stablizedPos); } return HMatrix; } Size VideoStabilizer::trimedVideoSize(Size frameSize) { Size outputFrameSize; outputFrameSize.width = ((int)((float)frameSize.width * (1 - 2 * trimRatio_)) >> 3) << 3; outputFrameSize.height = ((int)((float)frameSize.height * (1 - 2 * trimRatio_)) >> 3) << 3; return (outputFrameSize); } Mat VideoStabilizer::cropVideoFrame(Mat& frame) { Rect cropROI; Size inputFrameSize = frame.size(); Size outputFrameSize = trimedVideoSize(inputFrameSize); cropROI.x = (inputFrameSize.width - outputFrameSize.width) >> 1; cropROI.y = (inputFrameSize.height - outputFrameSize.height) >> 1; cropROI.width = outputFrameSize.width; cropROI.height = outputFrameSize.height; Mat croppedFrame = frame(cropROI).clone(); return croppedFrame; }