added minEigThreshold parameter to calcOpticalFlowPyrLK to filter out bad points earlier.
This commit is contained in:
parent
6b5ea5931d
commit
eebe4860da
@ -318,12 +318,13 @@ enum { OPTFLOW_USE_INITIAL_FLOW=4, OPTFLOW_FARNEBACK_GAUSSIAN=256 };
|
|||||||
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(15,15), int maxLevel=3,
|
Size winSize=Size(21,21), int maxLevel=3,
|
||||||
TermCriteria criteria=TermCriteria(
|
TermCriteria criteria=TermCriteria(
|
||||||
TermCriteria::COUNT+TermCriteria::EPS,
|
TermCriteria::COUNT+TermCriteria::EPS,
|
||||||
30, 0.01),
|
30, 0.01),
|
||||||
double derivLambda=0.5,
|
double derivLambda=0.5,
|
||||||
int flags=0 );
|
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,
|
||||||
|
@ -134,7 +134,7 @@ struct LKTrackerInvoker
|
|||||||
const Point2f* _prevPts, Point2f* _nextPts,
|
const Point2f* _prevPts, Point2f* _nextPts,
|
||||||
uchar* _status, float* _err,
|
uchar* _status, float* _err,
|
||||||
Size _winSize, TermCriteria _criteria,
|
Size _winSize, TermCriteria _criteria,
|
||||||
int _level, int _maxLevel, int _flags )
|
int _level, int _maxLevel, int _flags, float _minEigThreshold )
|
||||||
{
|
{
|
||||||
prevImg = &_prevImg;
|
prevImg = &_prevImg;
|
||||||
prevDeriv = &_prevDeriv;
|
prevDeriv = &_prevDeriv;
|
||||||
@ -148,6 +148,7 @@ struct LKTrackerInvoker
|
|||||||
level = _level;
|
level = _level;
|
||||||
maxLevel = _maxLevel;
|
maxLevel = _maxLevel;
|
||||||
flags = _flags;
|
flags = _flags;
|
||||||
|
minEigThreshold = _minEigThreshold;
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator()(const BlockedRange& range) const
|
void operator()(const BlockedRange& range) const
|
||||||
@ -308,11 +309,12 @@ struct LKTrackerInvoker
|
|||||||
|
|
||||||
float D = A11*A22 - A12*A12;
|
float D = A11*A22 - A12*A12;
|
||||||
float minEig = (A22 + A11 - std::sqrt((A11-A22)*(A11-A22) +
|
float minEig = (A22 + A11 - std::sqrt((A11-A22)*(A11-A22) +
|
||||||
4.f*A12*A12))/(2*winSize.width*winSize.height);
|
4.f*A12*A12))/(2*winSize.width*winSize.height);
|
||||||
if( err )
|
|
||||||
|
if( err && (flags & CV_LKFLOW_GET_MIN_EIGENVALS) != 0 )
|
||||||
err[ptidx] = (float)minEig;
|
err[ptidx] = (float)minEig;
|
||||||
|
|
||||||
if( D < FLT_EPSILON )
|
if( minEig < minEigThreshold || D < FLT_EPSILON )
|
||||||
{
|
{
|
||||||
if( level == 0 && status )
|
if( level == 0 && status )
|
||||||
status[ptidx] = false;
|
status[ptidx] = false;
|
||||||
@ -431,6 +433,46 @@ struct LKTrackerInvoker
|
|||||||
}
|
}
|
||||||
prevDelta = delta;
|
prevDelta = delta;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( status[ptidx] && err && level == 0 && (flags & CV_LKFLOW_GET_MIN_EIGENVALS) == 0 )
|
||||||
|
{
|
||||||
|
Point2f nextPt = nextPts[ptidx];
|
||||||
|
Point inextPt;
|
||||||
|
|
||||||
|
inextPt.x = cvFloor(nextPt.x);
|
||||||
|
inextPt.y = cvFloor(nextPt.y);
|
||||||
|
|
||||||
|
if( inextPt.x < -winSize.width || inextPt.x >= J.cols ||
|
||||||
|
inextPt.y < -winSize.height || inextPt.y >= J.rows )
|
||||||
|
{
|
||||||
|
if( status )
|
||||||
|
status[ptidx] = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
float a = nextPt.x - inextPt.x;
|
||||||
|
float b = nextPt.y - inextPt.y;
|
||||||
|
iw00 = cvRound((1.f - a)*(1.f - b)*(1 << W_BITS));
|
||||||
|
iw01 = cvRound(a*(1.f - b)*(1 << W_BITS));
|
||||||
|
iw10 = cvRound((1.f - a)*b*(1 << W_BITS));
|
||||||
|
iw11 = (1 << W_BITS) - iw00 - iw01 - iw10;
|
||||||
|
float errval = 0.f;
|
||||||
|
|
||||||
|
for( y = 0; y < winSize.height; y++ )
|
||||||
|
{
|
||||||
|
const uchar* Jptr = (const uchar*)J.data + (y + inextPt.y)*step + inextPt.x*cn;
|
||||||
|
const deriv_type* Iptr = (const deriv_type*)(IWinBuf.data + y*IWinBuf.step);
|
||||||
|
|
||||||
|
for( x = 0; x < winSize.width*cn; x++ )
|
||||||
|
{
|
||||||
|
int diff = CV_DESCALE(Jptr[x]*iw00 + Jptr[x+cn]*iw01 +
|
||||||
|
Jptr[x+step]*iw10 + Jptr[x+step+cn]*iw11,
|
||||||
|
W_BITS1-5) - Iptr[x];
|
||||||
|
errval += std::abs((float)diff);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
err[ptidx] = errval * 1.f/(32*winSize.width*cn*winSize.height);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -446,6 +488,7 @@ struct LKTrackerInvoker
|
|||||||
int level;
|
int level;
|
||||||
int maxLevel;
|
int maxLevel;
|
||||||
int flags;
|
int flags;
|
||||||
|
float minEigThreshold;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -456,7 +499,7 @@ void cv::calcOpticalFlowPyrLK( InputArray _prevImg, InputArray _nextImg,
|
|||||||
Size winSize, int maxLevel,
|
Size winSize, int maxLevel,
|
||||||
TermCriteria criteria,
|
TermCriteria criteria,
|
||||||
double derivLambda,
|
double derivLambda,
|
||||||
int flags )
|
int flags, double minEigThreshold )
|
||||||
{
|
{
|
||||||
#ifdef HAVE_TEGRA_OPTIMIZATION
|
#ifdef HAVE_TEGRA_OPTIMIZATION
|
||||||
if (tegra::calcOpticalFlowPyrLK(_prevImg, _nextImg, _prevPts, _nextPts, _status, _err, winSize, maxLevel, criteria, derivLambda, flags))
|
if (tegra::calcOpticalFlowPyrLK(_prevImg, _nextImg, _prevPts, _nextPts, _status, _err, winSize, maxLevel, criteria, derivLambda, flags))
|
||||||
@ -570,7 +613,8 @@ void cv::calcOpticalFlowPyrLK( InputArray _prevImg, InputArray _nextImg,
|
|||||||
parallel_for(BlockedRange(0, npoints), LKTrackerInvoker(prevPyr[level], derivI,
|
parallel_for(BlockedRange(0, npoints), LKTrackerInvoker(prevPyr[level], derivI,
|
||||||
nextPyr[level], prevPts, nextPts,
|
nextPyr[level], prevPts, nextPts,
|
||||||
status, err,
|
status, err,
|
||||||
winSize, criteria, level, maxLevel, flags));
|
winSize, criteria, level, maxLevel,
|
||||||
|
flags, (float)minEigThreshold));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@ int main( int argc, char** argv )
|
|||||||
{
|
{
|
||||||
VideoCapture cap;
|
VideoCapture cap;
|
||||||
TermCriteria termcrit(CV_TERMCRIT_ITER|CV_TERMCRIT_EPS,20,0.03);
|
TermCriteria termcrit(CV_TERMCRIT_ITER|CV_TERMCRIT_EPS,20,0.03);
|
||||||
Size winSize(10,10);
|
Size subPixWinSize(10,10), winSize(31,31);
|
||||||
|
|
||||||
const int MAX_COUNT = 500;
|
const int MAX_COUNT = 500;
|
||||||
bool needToInit = false;
|
bool needToInit = false;
|
||||||
@ -81,7 +81,7 @@ int main( int argc, char** argv )
|
|||||||
{
|
{
|
||||||
// automatic initialization
|
// automatic initialization
|
||||||
goodFeaturesToTrack(gray, points[1], MAX_COUNT, 0.01, 10, Mat(), 3, 0, 0.04);
|
goodFeaturesToTrack(gray, points[1], MAX_COUNT, 0.01, 10, Mat(), 3, 0, 0.04);
|
||||||
cornerSubPix(gray, points[1], winSize, Size(-1,-1), termcrit);
|
cornerSubPix(gray, points[1], subPixWinSize, Size(-1,-1), termcrit);
|
||||||
addRemovePt = false;
|
addRemovePt = false;
|
||||||
}
|
}
|
||||||
else if( !points[0].empty() )
|
else if( !points[0].empty() )
|
||||||
@ -91,7 +91,7 @@ int main( int argc, char** argv )
|
|||||||
if(prevGray.empty())
|
if(prevGray.empty())
|
||||||
gray.copyTo(prevGray);
|
gray.copyTo(prevGray);
|
||||||
calcOpticalFlowPyrLK(prevGray, gray, points[0], points[1], status, err, winSize,
|
calcOpticalFlowPyrLK(prevGray, gray, points[0], points[1], status, err, winSize,
|
||||||
3, termcrit, 0);
|
3, termcrit, 0, 0, 0.001);
|
||||||
size_t i, k;
|
size_t i, k;
|
||||||
for( i = k = 0; i < points[1].size(); i++ )
|
for( i = k = 0; i < points[1].size(); i++ )
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user