Wrap SparseOptFlow class around PyrLK optical flow computation
authoralcinos <carion.nicolas@gmail.com>
Thu, 28 Jan 2016 17:45:52 +0000 (18:45 +0100)
committeralcinos <carion.nicolas@gmail.com>
Fri, 29 Jan 2016 00:47:51 +0000 (01:47 +0100)
modules/cudaoptflow/src/pyrlk.cpp
modules/video/include/opencv2/video/tracking.hpp
modules/video/src/lkpyramid.cpp

index dcfd1f6..c7f7060 100644 (file)
@@ -47,9 +47,9 @@ using namespace cv::cuda;
 
 #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) */
 
@@ -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<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);
 }
 
-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);
 }
 
-#endif /* !defined (HAVE_CUDA) */
\ No newline at end of file
+#endif /* !defined (HAVE_CUDA) */
index 983a0c3..996e60b 100644 (file)
@@ -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
 
 } // cv
index 891ae78..25614d9 100644 (file)
@@ -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<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
 {