From e22b838af8a0078ca472583d76d0244dc9fad455 Mon Sep 17 00:00:00 2001 From: alcinos Date: Thu, 28 Jan 2016 18:45:52 +0100 Subject: [PATCH] Wrap SparseOptFlow class around PyrLK optical flow computation --- modules/cudaoptflow/src/pyrlk.cpp | 12 +-- modules/video/include/opencv2/video/tracking.hpp | 34 +++++++ modules/video/src/lkpyramid.cpp | 112 ++++++++++++++--------- 3 files changed, 107 insertions(+), 51 deletions(-) diff --git a/modules/cudaoptflow/src/pyrlk.cpp b/modules/cudaoptflow/src/pyrlk.cpp index dcfd1f6..c7f7060 100644 --- a/modules/cudaoptflow/src/pyrlk.cpp +++ b/modules/cudaoptflow/src/pyrlk.cpp @@ -47,9 +47,9 @@ using namespace cv::cuda; #if !defined (HAVE_CUDA) || defined (CUDA_DISABLER) -Ptr cv::cuda::SparsePyrLKOpticalFlow::create(Size, int, int, bool) { throw_no_cuda(); return Ptr(); } +Ptr cv::cuda::SparsePyrLKOpticalFlow::create(Size, int, int, bool) { throw_no_cuda(); return Ptr(); } -Ptr cv::cuda::DensePyrLKOpticalFlow::create(Size, int, int, bool) { throw_no_cuda(); return Ptr(); } +Ptr cv::cuda::DensePyrLKOpticalFlow::create(Size, int, int, bool) { throw_no_cuda(); return Ptr(); } #else /* !defined (HAVE_CUDA) */ @@ -283,7 +283,7 @@ namespace vPyr[idx].copyTo(v, stream); } - class SparsePyrLKOpticalFlowImpl : public SparsePyrLKOpticalFlow, private PyrLKOpticalFlowBase + class SparsePyrLKOpticalFlowImpl : public cv::cuda::SparsePyrLKOpticalFlow, private PyrLKOpticalFlowBase { public: SparsePyrLKOpticalFlowImpl(Size winSize, int maxLevel, int iters, bool useInitialFlow) : @@ -366,14 +366,14 @@ namespace }; } -Ptr cv::cuda::SparsePyrLKOpticalFlow::create(Size winSize, int maxLevel, int iters, bool useInitialFlow) +Ptr cv::cuda::SparsePyrLKOpticalFlow::create(Size winSize, int maxLevel, int iters, bool useInitialFlow) { return makePtr(winSize, maxLevel, iters, useInitialFlow); } -Ptr cv::cuda::DensePyrLKOpticalFlow::create(Size winSize, int maxLevel, int iters, bool useInitialFlow) +Ptr cv::cuda::DensePyrLKOpticalFlow::create(Size winSize, int maxLevel, int iters, bool useInitialFlow) { return makePtr(winSize, maxLevel, iters, useInitialFlow); } -#endif /* !defined (HAVE_CUDA) */ \ No newline at end of file +#endif /* !defined (HAVE_CUDA) */ diff --git a/modules/video/include/opencv2/video/tracking.hpp b/modules/video/include/opencv2/video/tracking.hpp index 983a0c3..996e60b 100644 --- a/modules/video/include/opencv2/video/tracking.hpp +++ b/modules/video/include/opencv2/video/tracking.hpp @@ -585,6 +585,40 @@ public: }; +/** @brief Class used for calculating a sparse optical flow. + +The class can calculate an optical flow for a sparse feature set using the +iterative Lucas-Kanade method with pyramids. + +@sa calcOpticalFlowPyrLK + +*/ +class CV_EXPORTS SparsePyrLKOpticalFlow : public SparseOpticalFlow +{ +public: + virtual Size getWinSize() const = 0; + virtual void setWinSize(Size winSize) = 0; + + virtual int getMaxLevel() const = 0; + virtual void setMaxLevel(int maxLevel) = 0; + + virtual TermCriteria getTermCriteria() const = 0; + virtual void setTermCriteria(TermCriteria& crit) = 0; + + virtual int getFlags() const = 0; + virtual void setFlags(int flags) = 0; + + virtual double getMinEigThreshold() const = 0; + virtual void setMinEigThreshold(double minEigThreshold) = 0; + + static Ptr create( + Size winSize = Size(21, 21), + int maxLevel = 3, TermCriteria crit = + TermCriteria(TermCriteria::COUNT+TermCriteria::EPS, 30, 0.01), + int flags = 0, + double minEigThreshold = 1e-4); +}; + //! @} video_track } // cv diff --git a/modules/video/src/lkpyramid.cpp b/modules/video/src/lkpyramid.cpp index 891ae78..25614d9 100644 --- a/modules/video/src/lkpyramid.cpp +++ b/modules/video/src/lkpyramid.cpp @@ -837,10 +837,11 @@ int cv::buildOpticalFlowPyramid(InputArray _img, OutputArrayOfArrays pyramid, Si return maxLevel; } -#ifdef HAVE_OPENCL namespace cv { - class PyrLKOpticalFlow +namespace +{ + class SparsePyrLKOpticalFlowImpl : public SparsePyrLKOpticalFlow { struct dim3 { @@ -848,17 +849,40 @@ namespace cv dim3() : x(0), y(0), z(0) { } }; public: - PyrLKOpticalFlow() + SparsePyrLKOpticalFlowImpl(Size winSize_ = Size(21,21), + int maxLevel_ = 3, + TermCriteria criteria_ = TermCriteria(TermCriteria::COUNT+TermCriteria::EPS, 30, 0.01), + int flags_ = 0, + double minEigThreshold_ = 1e-4) : + winSize(winSize_), maxLevel(maxLevel_), criteria(criteria_), flags(flags_), minEigThreshold(minEigThreshold_) +#ifdef HAVE_OPENCL + , iters(criteria_.maxCount), derivLambda(criteria_.epsilon), useInitialFlow(0 != (flags_ & OPTFLOW_LK_GET_MIN_EIGENVALS)), waveSize(0) +#endif { - winSize = Size(21, 21); - maxLevel = 3; - iters = 30; - derivLambda = 0.5; - useInitialFlow = false; - - waveSize = 0; } + virtual Size getWinSize() const {return winSize;} + virtual void setWinSize(Size winSize_){winSize = winSize_;} + + virtual int getMaxLevel() const {return maxLevel;} + virtual void setMaxLevel(int maxLevel_){maxLevel = maxLevel_;} + + virtual TermCriteria getTermCriteria() const {return criteria;} + virtual void setTermCriteria(TermCriteria& crit_){criteria=crit_;} + + virtual int getFlags() const {return flags; } + virtual void setFlags(int flags_){flags=flags_;} + + virtual double getMinEigThreshold() const {return minEigThreshold;} + virtual void setMinEigThreshold(double minEigThreshold_){minEigThreshold=minEigThreshold_;} + + virtual void calc(InputArray prevImg, InputArray nextImg, + InputArray prevPts, InputOutputArray nextPts, + OutputArray status, + OutputArray err = cv::noArray()); + + private: +#ifdef HAVE_OPENCL bool checkParam() { iters = std::min(std::max(iters, 0), 100); @@ -930,14 +954,17 @@ namespace cv } return true; } +#endif Size winSize; int maxLevel; + TermCriteria criteria; + int flags; + double minEigThreshold; +#ifdef HAVE_OPENCL int iters; double derivLambda; bool useInitialFlow; - - private: int waveSize; bool initWaveSize() { @@ -1017,15 +1044,11 @@ namespace cv { return (cv::ocl::Device::TYPE_CPU == cv::ocl::Device::getDefault().type()); } - }; - static bool ocl_calcOpticalFlowPyrLK(InputArray _prevImg, InputArray _nextImg, - InputArray _prevPts, InputOutputArray _nextPts, - OutputArray _status, OutputArray _err, - Size winSize, int maxLevel, - TermCriteria criteria, - int flags/*, double minEigThreshold*/ ) + bool ocl_calcOpticalFlowPyrLK(InputArray _prevImg, InputArray _nextImg, + InputArray _prevPts, InputOutputArray _nextPts, + OutputArray _status, OutputArray _err) { if (0 != (OPTFLOW_LK_GET_MIN_EIGENVALS & flags)) return false; @@ -1045,7 +1068,6 @@ namespace cv if ((1 != _prevPts.size().height) && (1 != _prevPts.size().width)) return false; size_t npoints = _prevPts.total(); - bool useInitialFlow = (0 != (flags & OPTFLOW_USE_INITIAL_FLOW)); if (useInitialFlow) { if (_nextPts.empty() || _nextPts.type() != CV_32FC2 || (!_prevPts.isContinuous())) @@ -1060,14 +1082,7 @@ namespace cv _nextPts.create(_prevPts.size(), _prevPts.type()); } - PyrLKOpticalFlow opticalFlow; - opticalFlow.winSize = winSize; - opticalFlow.maxLevel = maxLevel; - opticalFlow.iters = criteria.maxCount; - opticalFlow.derivLambda = criteria.epsilon; - opticalFlow.useInitialFlow = useInitialFlow; - - if (!opticalFlow.checkParam()) + if (!checkParam()) return false; UMat umatErr; @@ -1082,28 +1097,19 @@ namespace cv _status.create((int)npoints, 1, CV_8UC1); UMat umatNextPts = _nextPts.getUMat(); UMat umatStatus = _status.getUMat(); - return opticalFlow.sparse(_prevImg.getUMat(), _nextImg.getUMat(), _prevPts.getUMat(), umatNextPts, umatStatus, umatErr); + return sparse(_prevImg.getUMat(), _nextImg.getUMat(), _prevPts.getUMat(), umatNextPts, umatStatus, umatErr); } -}; #endif +}; -void cv::calcOpticalFlowPyrLK( InputArray _prevImg, InputArray _nextImg, +void SparsePyrLKOpticalFlowImpl::calc( InputArray _prevImg, InputArray _nextImg, InputArray _prevPts, InputOutputArray _nextPts, - OutputArray _status, OutputArray _err, - Size winSize, int maxLevel, - TermCriteria criteria, - int flags, double minEigThreshold ) + OutputArray _status, OutputArray _err) { -#ifdef HAVE_OPENCL - bool use_opencl = ocl::useOpenCL() && - (_prevImg.isUMat() || _nextImg.isUMat()) && - ocl::Image2D::isFormatSupported(CV_32F, 1, false); - if ( use_opencl && ocl_calcOpticalFlowPyrLK(_prevImg, _nextImg, _prevPts, _nextPts, _status, _err, winSize, maxLevel, criteria, flags/*, minEigThreshold*/)) - { - CV_IMPL_ADD(CV_IMPL_OCL); - return; - } -#endif + CV_OCL_RUN(ocl::useOpenCL() && + (_prevImg.isUMat() || _nextImg.isUMat()) && + ocl::Image2D::isFormatSupported(CV_32F, 1, false), + ocl_calcOpticalFlowPyrLK(_prevImg, _nextImg, _prevPts, _nextPts, _status, _err)) Mat prevPtsMat = _prevPts.getMat(); const int derivDepth = DataType::depth; @@ -1262,6 +1268,22 @@ void cv::calcOpticalFlowPyrLK( InputArray _prevImg, InputArray _nextImg, } } +} // namespace +} // namespace cv +cv::Ptr cv::SparsePyrLKOpticalFlow::create(Size winSize, int maxLevel, TermCriteria crit, int flags, double minEigThreshold){ + return makePtr(winSize,maxLevel,crit,flags,minEigThreshold); +} +void cv::calcOpticalFlowPyrLK( InputArray _prevImg, InputArray _nextImg, + InputArray _prevPts, InputOutputArray _nextPts, + OutputArray _status, OutputArray _err, + Size winSize, int maxLevel, + TermCriteria criteria, + int flags, double minEigThreshold ) +{ + Ptr optflow = cv::SparsePyrLKOpticalFlow::create(winSize,maxLevel,criteria,flags,minEigThreshold); + optflow->calc(_prevImg,_nextImg,_prevPts,_nextPts,_status,_err); +} + namespace cv { -- 2.7.4