Refactored per-computed pyramid handling in calcOpticalFlowPyrLK #1321
This commit is contained in:
parent
00c30681bc
commit
8f3273bf07
@ -48,7 +48,7 @@
|
|||||||
#define __OPENCV_TRACKING_HPP__
|
#define __OPENCV_TRACKING_HPP__
|
||||||
|
|
||||||
#include "opencv2/core/core.hpp"
|
#include "opencv2/core/core.hpp"
|
||||||
#include "opencv2/imgproc/imgproc_c.h"
|
#include "opencv2/imgproc/imgproc.hpp"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@ -303,16 +303,19 @@ enum
|
|||||||
OPTFLOW_FARNEBACK_GAUSSIAN = 256
|
OPTFLOW_FARNEBACK_GAUSSIAN = 256
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//! constructs a pyramid which can be used as input for calcOpticalFlowPyrLK
|
||||||
|
CV_EXPORTS_W int buildOpticalFlowPyramid(InputArray _img, OutputArrayOfArrays pyramid,
|
||||||
|
Size winSize, int maxLevel, bool withDerivatives = true,
|
||||||
|
int pyrBorder = BORDER_REFLECT_101, int derivBorder = BORDER_CONSTANT,
|
||||||
|
bool tryReuseInputImage = true);
|
||||||
|
|
||||||
//! computes sparse optical flow using multi-scale Lucas-Kanade algorithm
|
//! computes sparse optical flow using multi-scale Lucas-Kanade algorithm
|
||||||
CV_EXPORTS_W void calcOpticalFlowPyrLK( InputArray prevImg, InputArray nextImg,
|
CV_EXPORTS_W void calcOpticalFlowPyrLK( InputArray prevImg, InputArray nextImg,
|
||||||
InputArray prevPts, CV_OUT InputOutputArray nextPts,
|
InputArray prevPts, CV_OUT InputOutputArray nextPts,
|
||||||
OutputArray status, OutputArray err,
|
OutputArray status, OutputArray err,
|
||||||
Size winSize=Size(21,21), int maxLevel=3,
|
Size winSize=Size(21,21), int maxLevel=3,
|
||||||
TermCriteria criteria=TermCriteria(
|
TermCriteria criteria=TermCriteria(TermCriteria::COUNT+TermCriteria::EPS, 30, 0.01),
|
||||||
TermCriteria::COUNT+TermCriteria::EPS,
|
int flags=0, double minEigThreshold=1e-4);
|
||||||
30, 0.01),
|
|
||||||
int flags=0,
|
|
||||||
double minEigThreshold=1e-4);
|
|
||||||
|
|
||||||
//! computes dense optical flow using Farneback algorithm
|
//! computes dense optical flow using Farneback algorithm
|
||||||
CV_EXPORTS_W void calcOpticalFlowFarneback( InputArray prev, InputArray next,
|
CV_EXPORTS_W void calcOpticalFlowFarneback( InputArray prev, InputArray next,
|
||||||
|
@ -493,9 +493,9 @@ struct LKTrackerInvoker
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace cv {
|
|
||||||
int buildOpticalFlowPyramid(InputArray _img, OutputArrayOfArrays pyramid, Size winSize, int maxLevel, bool withDerivatives = true,
|
int cv::buildOpticalFlowPyramid(InputArray _img, OutputArrayOfArrays pyramid, Size winSize, int maxLevel, bool withDerivatives,
|
||||||
int pyrBorder = BORDER_REFLECT_101, int derivBorder=BORDER_CONSTANT, bool tryReuseInputImage = true)
|
int pyrBorder, int derivBorder, bool tryReuseInputImage)
|
||||||
{
|
{
|
||||||
Mat img = _img.getMat();
|
Mat img = _img.getMat();
|
||||||
CV_Assert(img.depth() == CV_8U && winSize.width > 2 && winSize.height > 2 );
|
CV_Assert(img.depth() == CV_8U && winSize.width > 2 && winSize.height > 2 );
|
||||||
@ -503,7 +503,6 @@ int buildOpticalFlowPyramid(InputArray _img, OutputArrayOfArrays pyramid, Size w
|
|||||||
|
|
||||||
pyramid.create(1, (maxLevel + 1) * pyrstep, 0 /*type*/, -1, true, 0);
|
pyramid.create(1, (maxLevel + 1) * pyrstep, 0 /*type*/, -1, true, 0);
|
||||||
|
|
||||||
//int cn = img.channels();
|
|
||||||
int derivType = CV_MAKETYPE(DataType<deriv_type>::depth, img.channels() * 2);
|
int derivType = CV_MAKETYPE(DataType<deriv_type>::depth, img.channels() * 2);
|
||||||
|
|
||||||
//level 0
|
//level 0
|
||||||
@ -589,8 +588,6 @@ int buildOpticalFlowPyramid(InputArray _img, OutputArrayOfArrays pyramid, Size w
|
|||||||
}
|
}
|
||||||
|
|
||||||
return maxLevel;
|
return maxLevel;
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void cv::calcOpticalFlowPyrLK( InputArray _prevImg, InputArray _nextImg,
|
void cv::calcOpticalFlowPyrLK( InputArray _prevImg, InputArray _nextImg,
|
||||||
@ -604,14 +601,12 @@ void cv::calcOpticalFlowPyrLK( InputArray _prevImg, InputArray _nextImg,
|
|||||||
if (tegra::calcOpticalFlowPyrLK(_prevImg, _nextImg, _prevPts, _nextPts, _status, _err, winSize, maxLevel, criteria, flags, minEigThreshold))
|
if (tegra::calcOpticalFlowPyrLK(_prevImg, _nextImg, _prevPts, _nextPts, _status, _err, winSize, maxLevel, criteria, flags, minEigThreshold))
|
||||||
return;
|
return;
|
||||||
#endif
|
#endif
|
||||||
Mat /*prevImg = _prevImg.getMat(), nextImg = _nextImg.getMat(),*/ prevPtsMat = _prevPts.getMat();
|
Mat prevPtsMat = _prevPts.getMat();
|
||||||
const int derivDepth = DataType<deriv_type>::depth;
|
const int derivDepth = DataType<deriv_type>::depth;
|
||||||
|
|
||||||
CV_Assert( maxLevel >= 0 && winSize.width > 2 && winSize.height > 2 );
|
CV_Assert( maxLevel >= 0 && winSize.width > 2 && winSize.height > 2 );
|
||||||
//CV_Assert( prevImg.size() == nextImg.size() &&
|
|
||||||
// prevImg.type() == nextImg.type() );
|
|
||||||
|
|
||||||
int level=0, i, npoints;//, cn = prevImg.channels(), cn2 = cn*2;
|
int level=0, i, npoints;
|
||||||
CV_Assert( (npoints = prevPtsMat.checkVector(2, CV_32F, true)) >= 0 );
|
CV_Assert( (npoints = prevPtsMat.checkVector(2, CV_32F, true)) >= 0 );
|
||||||
|
|
||||||
if( npoints == 0 )
|
if( npoints == 0 )
|
||||||
@ -649,42 +644,68 @@ void cv::calcOpticalFlowPyrLK( InputArray _prevImg, InputArray _nextImg,
|
|||||||
}
|
}
|
||||||
|
|
||||||
vector<Mat> prevPyr, nextPyr;
|
vector<Mat> prevPyr, nextPyr;
|
||||||
int levels1 = 0;
|
int levels1 = -1;
|
||||||
int lvlStep1 = 1;
|
int lvlStep1 = 1;
|
||||||
int levels2 = 0;
|
int levels2 = -1;
|
||||||
int lvlStep2 = 1;
|
int lvlStep2 = 1;
|
||||||
|
|
||||||
if(_prevImg.kind() == _InputArray::STD_VECTOR_MAT)
|
if(_prevImg.kind() == _InputArray::STD_VECTOR_MAT)
|
||||||
{
|
{
|
||||||
_prevImg.getMatVector(prevPyr);
|
_prevImg.getMatVector(prevPyr);
|
||||||
|
|
||||||
levels1 = (int)prevPyr.size();
|
levels1 = int(prevPyr.size()) - 1;
|
||||||
if (levels1 % 2 == 0 && levels1 > 1 && prevPyr[0].channels() * 2 == prevPyr[1].channels() && prevPyr[1].depth() == derivDepth)
|
CV_Assert(levels1 >= 0);
|
||||||
|
|
||||||
|
if (levels1 % 2 == 1 && prevPyr[0].channels() * 2 == prevPyr[1].channels() && prevPyr[1].depth() == derivDepth)
|
||||||
{
|
{
|
||||||
lvlStep1 = 2;
|
lvlStep1 = 2;
|
||||||
levels1 /= 2;
|
levels1 /= 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ensure that pyramid has reqired padding
|
||||||
|
if(levels1 > 0)
|
||||||
|
{
|
||||||
|
Size fullSize;
|
||||||
|
Point ofs;
|
||||||
|
prevPyr[lvlStep1].locateROI(fullSize, ofs);
|
||||||
|
CV_Assert(ofs.x >= winSize.width && ofs.y >= winSize.height
|
||||||
|
&& ofs.x + prevPyr[lvlStep1].cols + winSize.width <= fullSize.width
|
||||||
|
&& ofs.y + prevPyr[lvlStep1].rows + winSize.height <= fullSize.height);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(_nextImg.kind() == _InputArray::STD_VECTOR_MAT)
|
if(_nextImg.kind() == _InputArray::STD_VECTOR_MAT)
|
||||||
{
|
{
|
||||||
_nextImg.getMatVector(nextPyr);
|
_nextImg.getMatVector(nextPyr);
|
||||||
|
|
||||||
levels2 = (int)nextPyr.size();
|
levels2 = int(nextPyr.size()) - 1;
|
||||||
if (levels2 % 2 == 0 && levels2 > 1 && nextPyr[0].channels() * 2 == nextPyr[1].channels() && nextPyr[1].depth() == derivDepth)
|
CV_Assert(levels2 >= 0);
|
||||||
|
|
||||||
|
if (levels2 % 2 == 1 && nextPyr[0].channels() * 2 == nextPyr[1].channels() && nextPyr[1].depth() == derivDepth)
|
||||||
{
|
{
|
||||||
lvlStep2 = 2;
|
lvlStep2 = 2;
|
||||||
levels2 /= 2;
|
levels2 /= 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ensure that pyramid has reqired padding
|
||||||
|
if(levels2 > 0)
|
||||||
|
{
|
||||||
|
Size fullSize;
|
||||||
|
Point ofs;
|
||||||
|
nextPyr[lvlStep2].locateROI(fullSize, ofs);
|
||||||
|
CV_Assert(ofs.x >= winSize.width && ofs.y >= winSize.height
|
||||||
|
&& ofs.x + nextPyr[lvlStep2].cols + winSize.width <= fullSize.width
|
||||||
|
&& ofs.y + nextPyr[lvlStep2].rows + winSize.height <= fullSize.height);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(levels1 != 0 || levels2 != 0)
|
if(levels1 >= 0 || levels2 >= 0)
|
||||||
maxLevel = std::max(levels1, levels2);
|
maxLevel = std::max(levels1, levels2);
|
||||||
|
|
||||||
if (levels1 == 0)
|
if (levels1 < 0)
|
||||||
maxLevel = levels1 = buildOpticalFlowPyramid(_prevImg, prevPyr, winSize, maxLevel, false);
|
maxLevel = levels1 = buildOpticalFlowPyramid(_prevImg, prevPyr, winSize, maxLevel, false);
|
||||||
|
|
||||||
if (levels2 == 0)
|
if (levels2 < 0)
|
||||||
levels2 = buildOpticalFlowPyramid(_nextImg, nextPyr, winSize, maxLevel, false);
|
levels2 = buildOpticalFlowPyramid(_nextImg, nextPyr, winSize, maxLevel, false);
|
||||||
|
|
||||||
CV_Assert(levels1 == levels2);
|
CV_Assert(levels1 == levels2);
|
||||||
@ -700,43 +721,34 @@ void cv::calcOpticalFlowPyrLK( InputArray _prevImg, InputArray _nextImg,
|
|||||||
criteria.epsilon = std::min(std::max(criteria.epsilon, 0.), 10.);
|
criteria.epsilon = std::min(std::max(criteria.epsilon, 0.), 10.);
|
||||||
criteria.epsilon *= criteria.epsilon;
|
criteria.epsilon *= criteria.epsilon;
|
||||||
|
|
||||||
|
// dI/dx ~ Ix, dI/dy ~ Iy
|
||||||
|
Mat derivIBuf;
|
||||||
if(lvlStep1 == 1)
|
if(lvlStep1 == 1)
|
||||||
{
|
derivIBuf.create(prevPyr[0].rows + winSize.height*2, prevPyr[0].cols + winSize.width*2, CV_MAKETYPE(derivDepth, prevPyr[0].channels() * 2));
|
||||||
// dI/dx ~ Ix, dI/dy ~ Iy
|
|
||||||
Mat derivIBuf((prevPyr[0].rows + winSize.height*2),
|
|
||||||
(prevPyr[0].cols + winSize.width*2),
|
|
||||||
CV_MAKETYPE(derivDepth, prevPyr[0].channels() * 2));
|
|
||||||
|
|
||||||
for( level = maxLevel; level >= 0; level-- )
|
for( level = maxLevel; level >= 0; level-- )
|
||||||
|
{
|
||||||
|
Mat derivI;
|
||||||
|
if(lvlStep1 == 1)
|
||||||
{
|
{
|
||||||
Size imgSize = prevPyr[level * lvlStep1].size();
|
Size imgSize = prevPyr[level * lvlStep1].size();
|
||||||
Mat _derivI( imgSize.height + winSize.height*2,
|
Mat _derivI( imgSize.height + winSize.height*2,
|
||||||
imgSize.width + winSize.width*2, derivIBuf.type(), derivIBuf.data );
|
imgSize.width + winSize.width*2, derivIBuf.type(), derivIBuf.data );
|
||||||
Mat derivI = _derivI(Rect(winSize.width, winSize.height, imgSize.width, imgSize.height));
|
derivI = _derivI(Rect(winSize.width, winSize.height, imgSize.width, imgSize.height));
|
||||||
calcSharrDeriv(prevPyr[level * lvlStep1], derivI);
|
calcSharrDeriv(prevPyr[level * lvlStep1], derivI);
|
||||||
copyMakeBorder(derivI, _derivI, winSize.height, winSize.height, winSize.width, winSize.width, BORDER_CONSTANT|BORDER_ISOLATED);
|
copyMakeBorder(derivI, _derivI, winSize.height, winSize.height, winSize.width, winSize.width, BORDER_CONSTANT|BORDER_ISOLATED);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
derivI = prevPyr[level * lvlStep1 + 1];
|
||||||
|
|
||||||
CV_Assert(prevPyr[level * lvlStep1].size() == nextPyr[level * lvlStep2].size());
|
CV_Assert(prevPyr[level * lvlStep1].size() == nextPyr[level * lvlStep2].size());
|
||||||
CV_Assert(prevPyr[level * lvlStep1].type() == nextPyr[level * lvlStep2].type());
|
CV_Assert(prevPyr[level * lvlStep1].type() == nextPyr[level * lvlStep2].type());
|
||||||
parallel_for(BlockedRange(0, npoints), LKTrackerInvoker(prevPyr[level * lvlStep1], derivI,
|
|
||||||
nextPyr[level * lvlStep2], prevPts, nextPts,
|
parallel_for(BlockedRange(0, npoints), LKTrackerInvoker(prevPyr[level * lvlStep1], derivI,
|
||||||
status, err,
|
nextPyr[level * lvlStep2], prevPts, nextPts,
|
||||||
winSize, criteria, level, maxLevel,
|
status, err,
|
||||||
flags, (float)minEigThreshold));
|
winSize, criteria, level, maxLevel,
|
||||||
}
|
flags, (float)minEigThreshold));
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for( level = levels1; level >= 0; level-- )
|
|
||||||
{
|
|
||||||
CV_Assert(prevPyr[level * lvlStep1].size() == nextPyr[level * lvlStep2].size());
|
|
||||||
CV_Assert(prevPyr[level * lvlStep1].type() == nextPyr[level * lvlStep2].type());
|
|
||||||
parallel_for(BlockedRange(0, npoints), LKTrackerInvoker(prevPyr[level * lvlStep1], prevPyr[level * lvlStep1 + 1],
|
|
||||||
nextPyr[level * lvlStep2], prevPts, nextPts,
|
|
||||||
status, err,
|
|
||||||
winSize, criteria, level, maxLevel,
|
|
||||||
flags, (float)minEigThreshold));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,7 +53,7 @@
|
|||||||
|
|
||||||
#include "opencv2/video/tracking.hpp"
|
#include "opencv2/video/tracking.hpp"
|
||||||
#include "opencv2/video/background_segm.hpp"
|
#include "opencv2/video/background_segm.hpp"
|
||||||
#include "opencv2/imgproc/imgproc.hpp"
|
#include "opencv2/imgproc/imgproc_c.h"
|
||||||
#include "opencv2/core/internal.hpp"
|
#include "opencv2/core/internal.hpp"
|
||||||
|
|
||||||
#ifdef HAVE_TEGRA_OPTIMIZATION
|
#ifdef HAVE_TEGRA_OPTIMIZATION
|
||||||
|
Loading…
x
Reference in New Issue
Block a user