Wrap SparseOptFlow class around PyrLK optical flow computation
This commit is contained in:
		| @@ -47,9 +47,9 @@ using namespace cv::cuda; | |||||||
|  |  | ||||||
| #if !defined (HAVE_CUDA) || defined (CUDA_DISABLER) | #if !defined (HAVE_CUDA) || defined (CUDA_DISABLER) | ||||||
|  |  | ||||||
| Ptr<SparsePyrLKOpticalFlow> cv::cuda::SparsePyrLKOpticalFlow::create(Size, int, int, bool) { throw_no_cuda(); return Ptr<SparsePyrLKOpticalFlow>(); } | Ptr<cv::cuda::SparsePyrLKOpticalFlow> cv::cuda::SparsePyrLKOpticalFlow::create(Size, int, int, bool) { throw_no_cuda(); return Ptr<SparsePyrLKOpticalFlow>(); } | ||||||
|  |  | ||||||
| Ptr<DensePyrLKOpticalFlow> cv::cuda::DensePyrLKOpticalFlow::create(Size, int, int, bool) { throw_no_cuda(); return Ptr<DensePyrLKOpticalFlow>(); } | Ptr<cv::cuda::DensePyrLKOpticalFlow> cv::cuda::DensePyrLKOpticalFlow::create(Size, int, int, bool) { throw_no_cuda(); return Ptr<DensePyrLKOpticalFlow>(); } | ||||||
|  |  | ||||||
| #else /* !defined (HAVE_CUDA) */ | #else /* !defined (HAVE_CUDA) */ | ||||||
|  |  | ||||||
| @@ -283,7 +283,7 @@ namespace | |||||||
|         vPyr[idx].copyTo(v, stream); |         vPyr[idx].copyTo(v, stream); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     class SparsePyrLKOpticalFlowImpl : public SparsePyrLKOpticalFlow, private PyrLKOpticalFlowBase |     class SparsePyrLKOpticalFlowImpl : public cv::cuda::SparsePyrLKOpticalFlow, private PyrLKOpticalFlowBase | ||||||
|     { |     { | ||||||
|     public: |     public: | ||||||
|         SparsePyrLKOpticalFlowImpl(Size winSize, int maxLevel, int iters, bool useInitialFlow) : |         SparsePyrLKOpticalFlowImpl(Size winSize, int maxLevel, int iters, bool useInitialFlow) : | ||||||
| @@ -366,14 +366,14 @@ namespace | |||||||
|     }; |     }; | ||||||
| } | } | ||||||
|  |  | ||||||
| Ptr<SparsePyrLKOpticalFlow> cv::cuda::SparsePyrLKOpticalFlow::create(Size winSize, int maxLevel, int iters, bool useInitialFlow) | Ptr<cv::cuda::SparsePyrLKOpticalFlow> cv::cuda::SparsePyrLKOpticalFlow::create(Size winSize, int maxLevel, int iters, bool useInitialFlow) | ||||||
| { | { | ||||||
|     return makePtr<SparsePyrLKOpticalFlowImpl>(winSize, maxLevel, iters, useInitialFlow); |     return makePtr<SparsePyrLKOpticalFlowImpl>(winSize, maxLevel, iters, useInitialFlow); | ||||||
| } | } | ||||||
|  |  | ||||||
| Ptr<DensePyrLKOpticalFlow> cv::cuda::DensePyrLKOpticalFlow::create(Size winSize, int maxLevel, int iters, bool useInitialFlow) | Ptr<cv::cuda::DensePyrLKOpticalFlow> cv::cuda::DensePyrLKOpticalFlow::create(Size winSize, int maxLevel, int iters, bool useInitialFlow) | ||||||
| { | { | ||||||
|     return makePtr<DensePyrLKOpticalFlowImpl>(winSize, maxLevel, iters, useInitialFlow); |     return makePtr<DensePyrLKOpticalFlowImpl>(winSize, maxLevel, iters, useInitialFlow); | ||||||
| } | } | ||||||
|  |  | ||||||
| #endif /* !defined (HAVE_CUDA) */ | #endif /* !defined (HAVE_CUDA) */ | ||||||
|   | |||||||
| @@ -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<SparsePyrLKOpticalFlow> 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 | //! @} video_track | ||||||
|  |  | ||||||
| } // cv | } // cv | ||||||
|   | |||||||
| @@ -837,10 +837,11 @@ int cv::buildOpticalFlowPyramid(InputArray _img, OutputArrayOfArrays pyramid, Si | |||||||
|     return maxLevel; |     return maxLevel; | ||||||
| } | } | ||||||
|  |  | ||||||
| #ifdef HAVE_OPENCL |  | ||||||
| namespace cv | namespace cv | ||||||
| { | { | ||||||
|     class PyrLKOpticalFlow | namespace | ||||||
|  | { | ||||||
|  |     class SparsePyrLKOpticalFlowImpl : public SparsePyrLKOpticalFlow | ||||||
|     { |     { | ||||||
|         struct dim3 |         struct dim3 | ||||||
|         { |         { | ||||||
| @@ -848,17 +849,40 @@ namespace cv | |||||||
|             dim3() : x(0), y(0), z(0) { } |             dim3() : x(0), y(0), z(0) { } | ||||||
|         }; |         }; | ||||||
|     public: |     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() |         bool checkParam() | ||||||
|         { |         { | ||||||
|             iters = std::min(std::max(iters, 0), 100); |             iters = std::min(std::max(iters, 0), 100); | ||||||
| @@ -930,14 +954,17 @@ namespace cv | |||||||
|             } |             } | ||||||
|             return true; |             return true; | ||||||
|         } |         } | ||||||
|  | #endif | ||||||
|  |  | ||||||
|         Size winSize; |         Size winSize; | ||||||
|         int maxLevel; |         int maxLevel; | ||||||
|  |         TermCriteria criteria; | ||||||
|  |         int flags; | ||||||
|  |         double minEigThreshold; | ||||||
|  | #ifdef HAVE_OPENCL | ||||||
|         int iters; |         int iters; | ||||||
|         double derivLambda; |         double derivLambda; | ||||||
|         bool useInitialFlow; |         bool useInitialFlow; | ||||||
|  |  | ||||||
|     private: |  | ||||||
|         int waveSize; |         int waveSize; | ||||||
|         bool initWaveSize() |         bool initWaveSize() | ||||||
|         { |         { | ||||||
| @@ -1017,15 +1044,11 @@ namespace cv | |||||||
|         { |         { | ||||||
|             return (cv::ocl::Device::TYPE_CPU == cv::ocl::Device::getDefault().type()); |             return (cv::ocl::Device::TYPE_CPU == cv::ocl::Device::getDefault().type()); | ||||||
|         } |         } | ||||||
|     }; |  | ||||||
|  |  | ||||||
|  |  | ||||||
|     static bool ocl_calcOpticalFlowPyrLK(InputArray _prevImg, InputArray _nextImg, |     bool ocl_calcOpticalFlowPyrLK(InputArray _prevImg, InputArray _nextImg, | ||||||
|                                   InputArray _prevPts, InputOutputArray _nextPts, |                                          InputArray _prevPts, InputOutputArray _nextPts, | ||||||
|                                   OutputArray _status, OutputArray _err, |                                          OutputArray _status, OutputArray _err) | ||||||
|                                   Size winSize, int maxLevel, |  | ||||||
|                                   TermCriteria criteria, |  | ||||||
|                                   int flags/*, double minEigThreshold*/ ) |  | ||||||
|     { |     { | ||||||
|         if (0 != (OPTFLOW_LK_GET_MIN_EIGENVALS & flags)) |         if (0 != (OPTFLOW_LK_GET_MIN_EIGENVALS & flags)) | ||||||
|             return false; |             return false; | ||||||
| @@ -1045,7 +1068,6 @@ namespace cv | |||||||
|         if ((1 != _prevPts.size().height) && (1 != _prevPts.size().width)) |         if ((1 != _prevPts.size().height) && (1 != _prevPts.size().width)) | ||||||
|             return false; |             return false; | ||||||
|         size_t npoints = _prevPts.total(); |         size_t npoints = _prevPts.total(); | ||||||
|         bool useInitialFlow  = (0 != (flags & OPTFLOW_USE_INITIAL_FLOW)); |  | ||||||
|         if (useInitialFlow) |         if (useInitialFlow) | ||||||
|         { |         { | ||||||
|             if (_nextPts.empty() || _nextPts.type() != CV_32FC2 || (!_prevPts.isContinuous())) |             if (_nextPts.empty() || _nextPts.type() != CV_32FC2 || (!_prevPts.isContinuous())) | ||||||
| @@ -1060,14 +1082,7 @@ namespace cv | |||||||
|             _nextPts.create(_prevPts.size(), _prevPts.type()); |             _nextPts.create(_prevPts.size(), _prevPts.type()); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         PyrLKOpticalFlow opticalFlow; |         if (!checkParam()) | ||||||
|         opticalFlow.winSize     = winSize; |  | ||||||
|         opticalFlow.maxLevel    = maxLevel; |  | ||||||
|         opticalFlow.iters       = criteria.maxCount; |  | ||||||
|         opticalFlow.derivLambda = criteria.epsilon; |  | ||||||
|         opticalFlow.useInitialFlow  = useInitialFlow; |  | ||||||
|  |  | ||||||
|         if (!opticalFlow.checkParam()) |  | ||||||
|             return false; |             return false; | ||||||
|  |  | ||||||
|         UMat umatErr; |         UMat umatErr; | ||||||
| @@ -1082,28 +1097,19 @@ namespace cv | |||||||
|         _status.create((int)npoints, 1, CV_8UC1); |         _status.create((int)npoints, 1, CV_8UC1); | ||||||
|         UMat umatNextPts = _nextPts.getUMat(); |         UMat umatNextPts = _nextPts.getUMat(); | ||||||
|         UMat umatStatus = _status.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 | ||||||
| }; | }; | ||||||
| #endif |  | ||||||
|  |  | ||||||
| void cv::calcOpticalFlowPyrLK( InputArray _prevImg, InputArray _nextImg, | void SparsePyrLKOpticalFlowImpl::calc( InputArray _prevImg, InputArray _nextImg, | ||||||
|                            InputArray _prevPts, InputOutputArray _nextPts, |                            InputArray _prevPts, InputOutputArray _nextPts, | ||||||
|                            OutputArray _status, OutputArray _err, |                            OutputArray _status, OutputArray _err) | ||||||
|                            Size winSize, int maxLevel, |  | ||||||
|                            TermCriteria criteria, |  | ||||||
|                            int flags, double minEigThreshold ) |  | ||||||
| { | { | ||||||
| #ifdef HAVE_OPENCL |     CV_OCL_RUN(ocl::useOpenCL() && | ||||||
|     bool use_opencl = ocl::useOpenCL() && |                (_prevImg.isUMat() || _nextImg.isUMat()) && | ||||||
|                       (_prevImg.isUMat() || _nextImg.isUMat()) && |                ocl::Image2D::isFormatSupported(CV_32F, 1, false), | ||||||
|                       ocl::Image2D::isFormatSupported(CV_32F, 1, false); |                ocl_calcOpticalFlowPyrLK(_prevImg, _nextImg, _prevPts, _nextPts, _status, _err)) | ||||||
|     if ( use_opencl && ocl_calcOpticalFlowPyrLK(_prevImg, _nextImg, _prevPts, _nextPts, _status, _err, winSize, maxLevel, criteria, flags/*, minEigThreshold*/)) |  | ||||||
|     { |  | ||||||
|         CV_IMPL_ADD(CV_IMPL_OCL); |  | ||||||
|         return; |  | ||||||
|     } |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
|     Mat prevPtsMat = _prevPts.getMat(); |     Mat prevPtsMat = _prevPts.getMat(); | ||||||
|     const int derivDepth = DataType<cv::detail::deriv_type>::depth; |     const int derivDepth = DataType<cv::detail::deriv_type>::depth; | ||||||
| @@ -1262,6 +1268,22 @@ void cv::calcOpticalFlowPyrLK( InputArray _prevImg, InputArray _nextImg, | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | } // namespace | ||||||
|  | } // namespace cv | ||||||
|  | cv::Ptr<cv::SparsePyrLKOpticalFlow> cv::SparsePyrLKOpticalFlow::create(Size winSize, int maxLevel, TermCriteria crit, int flags, double minEigThreshold){ | ||||||
|  |     return makePtr<SparsePyrLKOpticalFlowImpl>(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<cv::SparsePyrLKOpticalFlow> optflow = cv::SparsePyrLKOpticalFlow::create(winSize,maxLevel,criteria,flags,minEigThreshold); | ||||||
|  |     optflow->calc(_prevImg,_nextImg,_prevPts,_nextPts,_status,_err); | ||||||
|  | } | ||||||
|  |  | ||||||
| namespace cv | namespace cv | ||||||
| { | { | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 alcinos
					alcinos