📄 cvlkpyramid.cpp
字号:
{
for( i = 0; i < count; i++ )
status[i] = status[i] == 0;
goto func_exit;
}
}
#endif
/* buffer_size = <size for patches> + <size for pyramids> */
bufferBytes = (srcPatchLen + patchLen * 3) * sizeof( _patchI[0][0] ) * threadCount;
buffer = (uchar*)cvAlloc( bufferBytes );
if( !buffer )
{
result = CV_OUTOFMEM_ERR;
goto func_exit;
}
for( i = 0; i < threadCount; i++ )
{
_patchI[i] = i == 0 ? (float*)buffer : _Iy[i-1] + patchLen;
_patchJ[i] = _patchI[i] + srcPatchLen;
_Ix[i] = _patchJ[i] + patchLen;
_Iy[i] = _Ix[i] + patchLen;
}
memset( status, 1, count );
if( error )
memset( error, 0, count*sizeof(error[0]) );
if( !(flags & CV_LKFLOW_INITIAL_GUESSES) )
memcpy( featuresB, featuresA, count*sizeof(featuresA[0]));
/* do processing from top pyramid level (smallest image)
to the bottom (original image) */
for( l = level; l >= 0; l-- )
{
CvSize levelSize = size[l];
int levelStep = step[l];
{
#ifdef _OPENMP
#pragma omp parallel for num_threads(threadCount), schedule(dynamic)
#endif // _OPENMP
/* find flow for each given point */
for( i = 0; i < count; i++ )
{
CvPoint2D32f v;
CvPoint minI, maxI, minJ, maxJ;
CvSize isz, jsz;
int pt_status;
CvPoint2D32f u;
CvPoint prev_minJ = { -1, -1 }, prev_maxJ = { -1, -1 };
double Gxx = 0, Gxy = 0, Gyy = 0, D = 0;
float prev_mx = 0, prev_my = 0;
int j, x, y;
int threadIdx = cvGetThreadNum();
float* patchI = _patchI[threadIdx];
float* patchJ = _patchJ[threadIdx];
float* Ix = _Ix[threadIdx];
float* Iy = _Iy[threadIdx];
v.x = featuresB[i].x;
v.y = featuresB[i].y;
if( l < level )
{
v.x += v.x;
v.y += v.y;
}
else
{
v.x = (float)(v.x * scale[l]);
v.y = (float)(v.y * scale[l]);
}
pt_status = status[i];
if( !pt_status )
continue;
minI = maxI = minJ = maxJ = cvPoint( 0, 0 );
u.x = (float) (featuresA[i].x * scale[l]);
u.y = (float) (featuresA[i].y * scale[l]);
intersect( u, winSize, levelSize, &minI, &maxI );
isz = jsz = cvSize(maxI.x - minI.x + 2, maxI.y - minI.y + 2);
u.x += (minI.x - (patchSize.width - maxI.x + 1))*0.5f;
u.y += (minI.y - (patchSize.height - maxI.y + 1))*0.5f;
if( isz.width < 3 || isz.height < 3 ||
icvGetRectSubPix_8u32f_C1R( imgI[l], levelStep, levelSize,
patchI, isz.width*sizeof(patchI[0]), isz, u ) < 0 )
{
/* point is outside the image. take the next */
status[i] = 0;
continue;
}
icvCalcIxIy_32f( patchI, isz.width*sizeof(patchI[0]), Ix, Iy,
(isz.width-2)*sizeof(patchI[0]), isz, smoothKernel, patchJ );
for( j = 0; j < criteria.max_iter; j++ )
{
double bx = 0, by = 0;
float mx, my;
CvPoint2D32f _v;
intersect( v, winSize, levelSize, &minJ, &maxJ );
minJ.x = MAX( minJ.x, minI.x );
minJ.y = MAX( minJ.y, minI.y );
maxJ.x = MIN( maxJ.x, maxI.x );
maxJ.y = MIN( maxJ.y, maxI.y );
jsz = cvSize(maxJ.x - minJ.x, maxJ.y - minJ.y);
_v.x = v.x + (minJ.x - (patchSize.width - maxJ.x + 1))*0.5f;
_v.y = v.y + (minJ.y - (patchSize.height - maxJ.y + 1))*0.5f;
if( jsz.width < 1 || jsz.height < 1 ||
icvGetRectSubPix_8u32f_C1R( imgJ[l], levelStep, levelSize, patchJ,
jsz.width*sizeof(patchJ[0]), jsz, _v ) < 0 )
{
/* point is outside image. take the next */
pt_status = 0;
break;
}
if( maxJ.x == prev_maxJ.x && maxJ.y == prev_maxJ.y &&
minJ.x == prev_minJ.x && minJ.y == prev_minJ.y )
{
for( y = 0; y < jsz.height; y++ )
{
const float* pi = patchI +
(y + minJ.y - minI.y + 1)*isz.width + minJ.x - minI.x + 1;
const float* pj = patchJ + y*jsz.width;
const float* ix = Ix +
(y + minJ.y - minI.y)*(isz.width-2) + minJ.x - minI.x;
const float* iy = Iy + (ix - Ix);
for( x = 0; x < jsz.width; x++ )
{
double t0 = pi[x] - pj[x];
bx += t0 * ix[x];
by += t0 * iy[x];
}
}
}
else
{
Gxx = Gyy = Gxy = 0;
for( y = 0; y < jsz.height; y++ )
{
const float* pi = patchI +
(y + minJ.y - minI.y + 1)*isz.width + minJ.x - minI.x + 1;
const float* pj = patchJ + y*jsz.width;
const float* ix = Ix +
(y + minJ.y - minI.y)*(isz.width-2) + minJ.x - minI.x;
const float* iy = Iy + (ix - Ix);
for( x = 0; x < jsz.width; x++ )
{
double t = pi[x] - pj[x];
bx += (double) (t * ix[x]);
by += (double) (t * iy[x]);
Gxx += ix[x] * ix[x];
Gxy += ix[x] * iy[x];
Gyy += iy[x] * iy[x];
}
}
D = Gxx * Gyy - Gxy * Gxy;
if( D < DBL_EPSILON )
{
pt_status = 0;
break;
}
D = 1. / D;
prev_minJ = minJ;
prev_maxJ = maxJ;
}
mx = (float) ((Gyy * bx - Gxy * by) * D);
my = (float) ((Gxx * by - Gxy * bx) * D);
v.x += mx;
v.y += my;
if( mx * mx + my * my < criteria.epsilon )
break;
if( j > 0 && fabs(mx + prev_mx) < 0.01 && fabs(my + prev_my) < 0.01 )
{
v.x -= mx*0.5f;
v.y -= my*0.5f;
break;
}
prev_mx = mx;
prev_my = my;
}
featuresB[i] = v;
status[i] = (char)pt_status;
if( l == 0 && error && pt_status )
{
/* calc error */
double err = 0;
for( y = 0; y < jsz.height; y++ )
{
const float* pi = patchI +
(y + minJ.y - minI.y + 1)*isz.width + minJ.x - minI.x + 1;
const float* pj = patchJ + y*jsz.width;
for( x = 0; x < jsz.width; x++ )
{
double t = pi[x] - pj[x];
err += t * t;
}
}
error[i] = (float)sqrt(err);
}
} // end of point processing loop (i)
}
} // end of pyramid levels loop (l)
func_exit:
if( ipp_optflow_state )
icvOpticalFlowPyrLKFree_8u_C1R_p( ipp_optflow_state );
cvFree( &pyrBuffer );
cvFree( &buffer );
cvFree( &_error );
cvFree( &_status );
return result;
#undef MAX_LEVEL
}
#if 0
/* Affine tracking algorithm */
static CvStatus icvCalcAffineFlowPyrLK_8uC1R( uchar * imgA, uchar * imgB,
int imgStep, CvSize imgSize,
uchar * pyrA, uchar * pyrB,
CvPoint2D32f * featuresA,
CvPoint2D32f * featuresB,
float *matrices, int count,
CvSize winSize, int level,
char *status, float *error,
CvTermCriteria criteria, int flags )
{
#define MAX_LEVEL 10
#define MAX_ITERS 100
static const float kerX[] = { -1, 0, 1 }, kerY[] =
{
0.09375, 0.3125, 0.09375}; /* 3/32, 10/32, 3/32 */
uchar *buffer = 0;
uchar *pyr_buffer = 0;
int bufferBytes = 0;
uchar **imgI = 0;
uchar **imgJ = 0;
int *step = 0;
double *scale = 0;
CvSize* size = 0;
float *patchI;
float *patchJ;
float *Ix;
float *Iy;
int i, j, k;
int x, y;
CvSize patchSize = cvSize( winSize.width * 2 + 1, winSize.height * 2 + 1 );
int patchLen = patchSize.width * patchSize.height;
int patchStep = patchSize.width * sizeof( patchI[0] );
CvSize srcPatchSize = cvSize( patchSize.width + 2, patchSize.height + 2 );
int srcPatchLen = srcPatchSize.width * srcPatchSize.height;
int srcPatchStep = srcPatchSize.width * sizeof( patchI[0] );
CvStatus result = CV_OK;
/* check input arguments */
if( !featuresA || !featuresB || !matrices )
return CV_NULLPTR_ERR;
if( winSize.width <= 1 || winSize.height <= 1 )
return CV_BADSIZE_ERR;
if( (flags & ~7) != 0 )
return CV_BADFLAG_ERR;
if( count <= 0 )
return CV_BADRANGE_ERR;
result = icvInitPyramidalAlgorithm( imgA, imgB, imgStep, imgSize,
pyrA, pyrB, level, &criteria, MAX_ITERS, flags,
&imgI, &imgJ, &step, &size, &scale, &pyr_buffer );
if( result < 0 )
goto func_exit;
/* buffer_size = <size for patches> + <size for pyramids> */
bufferBytes = (srcPatchLen + patchLen * 3) * sizeof( patchI[0] ) +
(36 * 2 + 6) * sizeof( double );
buffer = (uchar *) cvAlloc( bufferBytes );
if( !buffer )
{
result = CV_OUTOFMEM_ERR;
goto func_exit;
}
patchI = (float *) buffer;
patchJ = patchI + srcPatchLen;
Ix = patchJ + patchLen;
Iy = Ix + patchLen;
if( status )
memset( status, 1, count );
if( !(flags & CV_LKFLOW_INITIAL_GUESSES) )
{
memcpy( featuresB, featuresA, count * sizeof( featuresA[0] ));
for( i = 0; i < count * 4; i += 4 )
{
matrices[i] = matrices[i + 2] = 1.f;
matrices[i + 1] = matrices[i + 3] = 0.f;
}
}
/* find flow for each given point */
for( i = 0; i < count; i++ )
{
CvPoint2D32f v;
float A[4];
double G[36];
int l;
int pt_status = 1;
memcpy( A, matrices + i * 4, sizeof( A ));
v.x = (float) (featuresB[i].x * scale[level] * 0.5);
v.y = (float) (featuresB[i].y * scale[level] * 0.5);
/* do processing from top pyramid level (smallest image)
to the bottom (original image) */
for( l = level; l >= 0; l-- )
{
CvPoint2D32f u;
CvSize levelSize = size[l];
int x, y;
v.x += v.x;
v.y += v.y;
u.x = (float) (featuresA[i].x * scale[l]);
u.y = (float) (featuresA[i].y * scale[l]);
if( icvGetRectSubPix_8u32f_C1R( imgI[l], step[l], levelSize,
patchI, srcPatchStep, srcPatchSize, u ) < 0 )
{
/* point is outside the image. take the next */
pt_status = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -