Commit d62b0bd3 authored by Vadim Pisarevsky's avatar Vadim Pisarevsky

Merge pull request #6849 from alcinos:optflow_interface

parents 4da91f9e e22b838a
...@@ -361,6 +361,17 @@ Ptr<T> makePtr(const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& ...@@ -361,6 +361,17 @@ Ptr<T> makePtr(const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5&
return Ptr<T>(new T(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)); return Ptr<T>(new T(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10));
} }
template<typename T, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename A11>
Ptr<T> makePtr(const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7, const A8& a8, const A9& a9, const A10& a10, const A11& a11)
{
return Ptr<T>(new T(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11));
}
template<typename T, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename A11, typename A12>
Ptr<T> makePtr(const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7, const A8& a8, const A9& a9, const A10& a10, const A11& a11, const A12& a12)
{
return Ptr<T>(new T(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12));
}
} // namespace cv } // namespace cv
//! @endcond //! @endcond
......
...@@ -93,7 +93,7 @@ namespace cv { namespace cuda { namespace device { namespace optflow_farneback ...@@ -93,7 +93,7 @@ namespace cv { namespace cuda { namespace device { namespace optflow_farneback
namespace namespace
{ {
class FarnebackOpticalFlowImpl : public FarnebackOpticalFlow class FarnebackOpticalFlowImpl : public cv::cuda::FarnebackOpticalFlow
{ {
public: public:
FarnebackOpticalFlowImpl(int numLevels, double pyrScale, bool fastPyramids, int winSize, FarnebackOpticalFlowImpl(int numLevels, double pyrScale, bool fastPyramids, int winSize,
...@@ -459,7 +459,7 @@ namespace ...@@ -459,7 +459,7 @@ namespace
} }
} }
Ptr<FarnebackOpticalFlow> cv::cuda::FarnebackOpticalFlow::create(int numLevels, double pyrScale, bool fastPyramids, int winSize, Ptr<cv::cuda::FarnebackOpticalFlow> cv::cuda::FarnebackOpticalFlow::create(int numLevels, double pyrScale, bool fastPyramids, int winSize,
int numIters, int polyN, double polySigma, int flags) int numIters, int polyN, double polySigma, int flags)
{ {
return makePtr<FarnebackOpticalFlowImpl>(numLevels, pyrScale, fastPyramids, winSize, return makePtr<FarnebackOpticalFlowImpl>(numLevels, pyrScale, fastPyramids, winSize,
......
...@@ -47,9 +47,9 @@ using namespace cv::cuda; ...@@ -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 ...@@ -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 ...@@ -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) */
\ No newline at end of file
...@@ -397,6 +397,27 @@ public: ...@@ -397,6 +397,27 @@ public:
CV_WRAP virtual void collectGarbage() = 0; CV_WRAP virtual void collectGarbage() = 0;
}; };
/** @brief Base interface for sparse optical flow algorithms.
*/
class CV_EXPORTS_W SparseOpticalFlow : public Algorithm
{
public:
/** @brief Calculates a sparse optical flow.
@param prevImg First input image.
@param nextImg Second input image of the same size and the same type as prevImg.
@param prevPts Vector of 2D points for which the flow needs to be found.
@param nextPts Output vector of 2D points containing the calculated new positions of input features in the second image.
@param status Output status vector. Each element of the vector is set to 1 if the
flow for the corresponding features has been found. Otherwise, it is set to 0.
@param err Optional output vector that contains error response for each point (inverse confidence).
*/
CV_WRAP virtual void calc(InputArray prevImg, InputArray nextImg,
InputArray prevPts, InputOutputArray nextPts,
OutputArray status,
OutputArray err = cv::noArray()) = 0;
};
/** @brief "Dual TV L1" Optical Flow Algorithm. /** @brief "Dual TV L1" Optical Flow Algorithm.
The class implements the "Dual TV L1" optical flow algorithm described in @cite Zach2007 and The class implements the "Dual TV L1" optical flow algorithm described in @cite Zach2007 and
...@@ -502,12 +523,102 @@ public: ...@@ -502,12 +523,102 @@ public:
virtual int getMedianFiltering() const = 0; virtual int getMedianFiltering() const = 0;
/** @copybrief getMedianFiltering @see getMedianFiltering */ /** @copybrief getMedianFiltering @see getMedianFiltering */
virtual void setMedianFiltering(int val) = 0; virtual void setMedianFiltering(int val) = 0;
/** @brief Creates instance of cv::DualTVL1OpticalFlow*/
static Ptr<DualTVL1OpticalFlow> create(
double tau = 0.25,
double lambda = 0.15,
double theta = 0.3,
int nscales = 5,
int warps = 5,
double epsilon = 0.01,
int innnerIterations = 30,
int outerIterations = 10,
double scaleStep = 0.8,
double gamma = 0.0,
int medianFiltering = 5,
bool useInitialFlow = false);
}; };
/** @brief Creates instance of cv::DenseOpticalFlow /** @brief Creates instance of cv::DenseOpticalFlow
*/ */
CV_EXPORTS_W Ptr<DualTVL1OpticalFlow> createOptFlow_DualTVL1(); CV_EXPORTS_W Ptr<DualTVL1OpticalFlow> createOptFlow_DualTVL1();
/** @brief Class computing a dense optical flow using the Gunnar Farneback’s algorithm.
*/
class CV_EXPORTS_W FarnebackOpticalFlow : public DenseOpticalFlow
{
public:
virtual int getNumLevels() const = 0;
virtual void setNumLevels(int numLevels) = 0;
virtual double getPyrScale() const = 0;
virtual void setPyrScale(double pyrScale) = 0;
virtual bool getFastPyramids() const = 0;
virtual void setFastPyramids(bool fastPyramids) = 0;
virtual int getWinSize() const = 0;
virtual void setWinSize(int winSize) = 0;
virtual int getNumIters() const = 0;
virtual void setNumIters(int numIters) = 0;
virtual int getPolyN() const = 0;
virtual void setPolyN(int polyN) = 0;
virtual double getPolySigma() const = 0;
virtual void setPolySigma(double polySigma) = 0;
virtual int getFlags() const = 0;
virtual void setFlags(int flags) = 0;
static Ptr<FarnebackOpticalFlow> create(
int numLevels = 5,
double pyrScale = 0.5,
bool fastPyramids = false,
int winSize = 13,
int numIters = 10,
int polyN = 5,
double polySigma = 1.1,
int flags = 0);
};
/** @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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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, ...@@ -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
{ {
......
This diff is collapsed.
...@@ -89,6 +89,17 @@ namespace { ...@@ -89,6 +89,17 @@ namespace {
class OpticalFlowDual_TVL1 : public DualTVL1OpticalFlow class OpticalFlowDual_TVL1 : public DualTVL1OpticalFlow
{ {
public: public:
OpticalFlowDual_TVL1(double tau_, double lambda_, double theta_, int nscales_, int warps_,
double epsilon_, int innerIterations_, int outerIterations_,
double scaleStep_, double gamma_, int medianFiltering_,
bool useInitialFlow_) :
tau(tau_), lambda(lambda_), theta(theta_), gamma(gamma_), nscales(nscales_),
warps(warps_), epsilon(epsilon_), innerIterations(innerIterations_),
outerIterations(outerIterations_), useInitialFlow(useInitialFlow_),
scaleStep(scaleStep_), medianFiltering(medianFiltering_)
{
}
OpticalFlowDual_TVL1(); OpticalFlowDual_TVL1();
void calc(InputArray I0, InputArray I1, InputOutputArray flow); void calc(InputArray I0, InputArray I1, InputOutputArray flow);
...@@ -1450,3 +1461,13 @@ Ptr<DualTVL1OpticalFlow> cv::createOptFlow_DualTVL1() ...@@ -1450,3 +1461,13 @@ Ptr<DualTVL1OpticalFlow> cv::createOptFlow_DualTVL1()
{ {
return makePtr<OpticalFlowDual_TVL1>(); return makePtr<OpticalFlowDual_TVL1>();
} }
Ptr<DualTVL1OpticalFlow> cv::DualTVL1OpticalFlow::create(
double tau, double lambda, double theta, int nscales, int warps,
double epsilon, int innerIterations, int outerIterations, double scaleStep,
double gamma, int medianFilter, bool useInitialFlow)
{
return makePtr<OpticalFlowDual_TVL1>(tau, lambda, theta, nscales, warps,
epsilon, innerIterations, outerIterations,
scaleStep, gamma, medianFilter, useInitialFlow);
}
...@@ -154,7 +154,7 @@ TEST(Video_calcOpticalFlowDual_TVL1, Regression) ...@@ -154,7 +154,7 @@ TEST(Video_calcOpticalFlowDual_TVL1, Regression)
ASSERT_FALSE(frame2.empty()); ASSERT_FALSE(frame2.empty());
Mat_<Point2f> flow; Mat_<Point2f> flow;
Ptr<DenseOpticalFlow> tvl1 = createOptFlow_DualTVL1(); Ptr<DualTVL1OpticalFlow> tvl1 = cv::DualTVL1OpticalFlow::create();
tvl1->calc(frame1, frame2, flow); tvl1->calc(frame1, frame2, flow);
......
...@@ -185,7 +185,7 @@ int main(int argc, const char* argv[]) ...@@ -185,7 +185,7 @@ int main(int argc, const char* argv[])
} }
Mat_<Point2f> flow; Mat_<Point2f> flow;
Ptr<DenseOpticalFlow> tvl1 = createOptFlow_DualTVL1(); Ptr<DualTVL1OpticalFlow> tvl1 = cv::DualTVL1OpticalFlow::create();
const double start = (double)getTickCount(); const double start = (double)getTickCount();
tvl1->calc(frame0, frame1, flow); tvl1->calc(frame0, frame1, flow);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment