| /* |
| * 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 <[email protected]> |
| */ |
| |
| #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<KeypointBasedMotionEstimator>()->estimate(ugrayImage0, ugrayImage1); |
| #else |
| return motionEstimator_.dynamicCast<KeypointBasedMotionEstimator>()->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<KeypointBasedMotionEstimator>()->estimate(ugrayImage0, ugrayImage1); |
| #else |
| return motionEstimator_.dynamicCast<KeypointBasedMotionEstimator>()->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<MotionEstimatorRansacL2> est = makePtr<MotionEstimatorRansacL2>(MM_HOMOGRAPHY); |
| Ptr<IOutlierRejector> outlierRejector = makePtr<TranslationBasedLocalOutlierRejector>(); |
| Ptr<KeypointBasedMotionEstimator> kbest = makePtr<KeypointBasedMotionEstimator>(est); |
| kbest->setDetector(GFTTDetector::create(1000, 0.01, 15)); |
| kbest->setOutlierRejector(outlierRejector); |
| |
| if (isTwoPass) |
| { |
| Ptr<TwoPassVideoStabilizer> twoPassStabilizer = makePtr<TwoPassVideoStabilizer>(); |
| stabilizer_ = twoPassStabilizer; |
| twoPassStabilizer->setEstimateTrimRatio(false); |
| twoPassStabilizer->setMotionStabilizer(makePtr<GaussianMotionFilter>(15, 10)); |
| |
| if (wobbleSuppress) { |
| Ptr<MoreAccurateMotionWobbleSuppressorBase> ws = makePtr<MoreAccurateMotionWobbleSuppressor>(); |
| |
| ws->setMotionEstimator(kbest); |
| ws->setPeriod(30); |
| twoPassStabilizer->setWobbleSuppressor(ws); |
| } |
| } else { |
| Ptr<OnePassVideoStabilizer> onePassStabilizer = makePtr<OnePassVideoStabilizer>(); |
| stabilizer_ = onePassStabilizer; |
| onePassStabilizer->setMotionFilter(makePtr<GaussianMotionFilter>(15, 10)); |
| } |
| |
| stabilizer_->setMotionEstimator(kbest); |
| |
| stabilizer_->setRadius(15); |
| |
| if (deblur) |
| { |
| Ptr<WeightingDeblurer> deblurrer = makePtr<WeightingDeblurer>(); |
| 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<InpainterBase> inpainters_(inpainters); |
| if (true == inpaintMosaic) |
| { |
| Ptr<ConsistentMosaicInpainter> inp = makePtr<ConsistentMosaicInpainter>(); |
| inp->setStdevThresh(10.0f); |
| inpainters->pushBack(inp); |
| } |
| if (true == inpaintColorAverage) |
| inpainters->pushBack(makePtr<ColorAverageInpainter>()); |
| else if (true == inpaintColorNs) |
| inpainters->pushBack(makePtr<ColorInpainter>(0, 2)); |
| else if (true == inpaintColorTelea) |
| inpainters->pushBack(makePtr<ColorInpainter>(1, 2)); |
| if (!inpainters->empty()) |
| { |
| inpainters->setRadius(2); |
| stabilizer_->setInpainter(inpainters_); |
| } |
| } |
| } |
| |
| VideoStabilizer::~VideoStabilizer() {} |
| |
| void |
| VideoStabilizer::configFeatureDetector(int features, double minDistance) |
| { |
| Ptr<ImageMotionEstimatorBase> estimator = stabilizer_->motionEstimator(); |
| Ptr<FeatureDetector> detector = estimator.dynamicCast<KeypointBasedMotionEstimator>()->detector(); |
| if (NULL == detector) { |
| return; |
| } |
| |
| detector.dynamicCast<GFTTDetector>()->setMaxFeatures(features); |
| detector.dynamicCast<GFTTDetector>()->setMinDistance(minDistance); |
| } |
| |
| void |
| VideoStabilizer::configMotionFilter(int radius, float stdev) |
| { |
| if (isTwoPass_) { |
| Ptr<TwoPassVideoStabilizer> stab = stabilizer_.dynamicCast<TwoPassVideoStabilizer>(); |
| Ptr<IMotionStabilizer> motionStabilizer = stab->motionStabilizer(); |
| motionStabilizer.dynamicCast<GaussianMotionFilter>()->setParams(radius, stdev); |
| } else { |
| Ptr<OnePassVideoStabilizer> stab = stabilizer_.dynamicCast<OnePassVideoStabilizer>(); |
| Ptr<MotionFilterBase> motionFilter = stab->motionFilter(); |
| motionFilter.dynamicCast<GaussianMotionFilter>()->setParams(radius, stdev); |
| } |
| stabilizer_->setRadius(radius); |
| } |
| |
| void |
| VideoStabilizer::configDeblurrer(int radius, double sensitivity) |
| { |
| Ptr<DeblurerBase> deblurrer = stabilizer_->deblurrer(); |
| if (NULL == deblurrer) { |
| return; |
| } |
| |
| deblurrer->setRadius(radius); |
| deblurrer.dynamicCast<WeightingDeblurer>()->setSensitivity(sensitivity); |
| } |
| |
| void |
| VideoStabilizer::setFrameSize(Size frameSize) |
| { |
| frameSize_ = frameSize; |
| } |
| |
| Mat |
| VideoStabilizer::nextFrame() |
| { |
| if (isTwoPass_) { |
| Ptr<TwoPassVideoStabilizer> stab = stabilizer_.dynamicCast<TwoPassVideoStabilizer>(); |
| return stab->nextFrame(); |
| } else { |
| Ptr<OnePassVideoStabilizer> stab = stabilizer_.dynamicCast<OnePassVideoStabilizer>(); |
| return stab->nextFrame(); |
| } |
| } |
| |
| Mat |
| VideoStabilizer::nextStabilizedMotion(DvsData* frame, int& stablizedPos) |
| { |
| Mat HMatrix; |
| |
| if (isTwoPass_) { |
| Ptr<TwoPassVideoStabilizer> stab = stabilizer_.dynamicCast<TwoPassVideoStabilizer>(); |
| HMatrix = stab->nextStabilizedMotion(frame, stablizedPos); |
| } else { |
| Ptr<OnePassVideoStabilizer> stab = stabilizer_.dynamicCast<OnePassVideoStabilizer>(); |
| 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; |
| } |
| |