📄 trackfeatures.c
字号:
float *x2, /* starting location of search in second image */
float *y2,
_KLT_FloatImage img1,
_KLT_FloatImage gradx1,
_KLT_FloatImage grady1,
_KLT_FloatImage img2,
_KLT_FloatImage gradx2,
_KLT_FloatImage grady2,
int width, /* size of window */
int height,
float step_factor, /* 2.0 comes from equations, 1.0 seems to avoid overshooting */
int max_iterations,
float small, /* determinant threshold for declaring KLT_SMALL_DET */
float th, /* displacement threshold for stopping */
float max_residue, /* residue threshold for declaring KLT_LARGE_RESIDUE */
int lighting_insensitive) /* whether to normalize for gain and bias */
{
_FloatWindow imgdiff, gradx, grady;
float gxx, gxy, gyy, ex, ey, dx, dy;
int iteration = 0;
int status;
int hw = width/2;
int hh = height/2;
int nc = img1->ncols;
int nr = img1->nrows;
float one_plus_eps = 1.001f; /* To prevent rounding errors */
/* Allocate memory for windows */
imgdiff = _allocateFloatWindow(width, height);
gradx = _allocateFloatWindow(width, height);
grady = _allocateFloatWindow(width, height);
/* Iteratively update the window position */
do {
/* If out of bounds, exit loop */
if ( x1-hw < 0.0f || nc-( x1+hw) < one_plus_eps ||
*x2-hw < 0.0f || nc-(*x2+hw) < one_plus_eps ||
y1-hh < 0.0f || nr-( y1+hh) < one_plus_eps ||
*y2-hh < 0.0f || nr-(*y2+hh) < one_plus_eps) {
status = KLT_OOB;
break;
}
/* Compute gradient and difference windows */
if (lighting_insensitive) {
_computeIntensityDifferenceLightingInsensitive(img1, img2, x1, y1, *x2, *y2,
width, height, imgdiff);
_computeGradientSumLightingInsensitive(gradx1, grady1, gradx2, grady2,
img1, img2, x1, y1, *x2, *y2, width, height, gradx, grady);
} else {
_computeIntensityDifference(img1, img2, x1, y1, *x2, *y2,
width, height, imgdiff);
_computeGradientSum(gradx1, grady1, gradx2, grady2,
x1, y1, *x2, *y2, width, height, gradx, grady);
}
/* Use these windows to construct matrices */
_compute2by2GradientMatrix(gradx, grady, width, height,
&gxx, &gxy, &gyy);
_compute2by1ErrorVector(imgdiff, gradx, grady, width, height, step_factor,
&ex, &ey);
/* Using matrices, solve equation for new displacement */
status = _solveEquation(gxx, gxy, gyy, ex, ey, small, &dx, &dy);
if (status == KLT_SMALL_DET) break;
*x2 += dx;
*y2 += dy;
iteration++;
} while ((fabs(dx)>=th || fabs(dy)>=th) && iteration < max_iterations);
/* Check whether window is out of bounds */
if (*x2-hw < 0.0f || nc-(*x2+hw) < one_plus_eps ||
*y2-hh < 0.0f || nr-(*y2+hh) < one_plus_eps)
status = KLT_OOB;
/* Check whether residue is too large */
if (status == KLT_TRACKED) {
if (lighting_insensitive)
_computeIntensityDifferenceLightingInsensitive(img1, img2, x1, y1, *x2, *y2,
width, height, imgdiff);
else
_computeIntensityDifference(img1, img2, x1, y1, *x2, *y2,
width, height, imgdiff);
if (_sumAbsFloatWindow(imgdiff, width, height)/(width*height) > max_residue)
status = KLT_LARGE_RESIDUE;
}
/* Free memory */
free(imgdiff); free(gradx); free(grady);
/* Return appropriate value */
if (status == KLT_SMALL_DET) return KLT_SMALL_DET;
else if (status == KLT_OOB) return KLT_OOB;
else if (status == KLT_LARGE_RESIDUE) return KLT_LARGE_RESIDUE;
else if (iteration >= max_iterations) return KLT_MAX_ITERATIONS;
else return KLT_TRACKED;
}
/*********************************************************************/
static KLT_BOOL _outOfBounds(
float x,
float y,
int ncols,
int nrows,
int borderx,
int bordery)
{
return (x < borderx || x > ncols-1-borderx ||
y < bordery || y > nrows-1-bordery );
}
/**********************************************************************
* CONSISTENCY CHECK OF FEATURES BY AFFINE MAPPING (BEGIN)
*
* Created by: Thorsten Thormaehlen (University of Hannover) June 2004
* thormae@tnt.uni-hannover.de
*
* Permission is granted to any individual or institution to use, copy, modify,
* and distribute this part of the software, provided that this complete authorship
* and permission notice is maintained, intact, in all copies.
*
* This software is provided "as is" without express or implied warranty.
*
*
* The following static functions are helpers for the affine mapping.
* They all start with "_am".
* There are also small changes in other files for the
* affine mapping these are all marked by "for affine mapping"
*
* Thanks to Kevin Koeser (koeser@mip.informatik.uni-kiel.de) for fixing a bug
*/
#define SWAP_ME(X,Y) {temp=(X);(X)=(Y);(Y)=temp;}
static float **_am_matrix(long nr, long nc)
{
float **m;
int a;
m = (float **) malloc((size_t)(nr*sizeof(float*)));
m[0] = (float *) malloc((size_t)((nr*nc)*sizeof(float)));
for(a = 1; a < nr; a++) m[a] = m[a-1]+nc;
return m;
}
static void _am_free_matrix(float **m)
{
free(m[0]);
free(m);
}
static int _am_gauss_jordan_elimination(float **a, int n, float **b, int m)
{
/* re-implemented from Numerical Recipes in C */
int *indxc,*indxr,*ipiv;
int i,j,k,l,ll;
float big,dum,pivinv,temp;
int col = 0;
int row = 0;
indxc=(int *)malloc((size_t) (n*sizeof(int)));
indxr=(int *)malloc((size_t) (n*sizeof(int)));
ipiv=(int *)malloc((size_t) (n*sizeof(int)));
for (j=0;j<n;j++) ipiv[j]=0;
for (i=0;i<n;i++) {
big=0.0;
for (j=0;j<n;j++)
if (ipiv[j] != 1)
for (k=0;k<n;k++) {
if (ipiv[k] == 0) {
if (fabs(a[j][k]) >= big) {
big= (float) fabs(a[j][k]);
row=j;
col=k;
}
} else if (ipiv[k] > 1) return KLT_SMALL_DET;
}
++(ipiv[col]);
if (row != col) {
for (l=0;l<n;l++) SWAP_ME(a[row][l],a[col][l])
for (l=0;l<m;l++) SWAP_ME(b[row][l],b[col][l])
}
indxr[i]=row;
indxc[i]=col;
if (a[col][col] == 0.0) return KLT_SMALL_DET;
pivinv=1.0f/a[col][col];
a[col][col]=1.0;
for (l=0;l<n;l++) a[col][l] *= pivinv;
for (l=0;l<m;l++) b[col][l] *= pivinv;
for (ll=0;ll<n;ll++)
if (ll != col) {
dum=a[ll][col];
a[ll][col]=0.0;
for (l=0;l<n;l++) a[ll][l] -= a[col][l]*dum;
for (l=0;l<m;l++) b[ll][l] -= b[col][l]*dum;
}
}
for (l=n-1;l>=0;l--) {
if (indxr[l] != indxc[l])
for (k=0;k<n;k++)
SWAP_ME(a[k][indxr[l]],a[k][indxc[l]]);
}
free(ipiv);
free(indxr);
free(indxc);
return KLT_TRACKED;
}
/*********************************************************************
* _am_getGradientWinAffine
*
* aligns the gradients with the affine transformed window
*/
static void _am_getGradientWinAffine(
_KLT_FloatImage in_gradx,
_KLT_FloatImage in_grady,
float x, float y, /* center of window*/
float Axx, float Ayx , float Axy, float Ayy, /* affine mapping */
int width, int height, /* size of window */
_FloatWindow out_gradx, /* output */
_FloatWindow out_grady) /* output */
{
register int hw = width/2, hh = height/2;
register int i, j;
float mi, mj;
/* Compute values */
for (j = -hh ; j <= hh ; j++)
for (i = -hw ; i <= hw ; i++) {
mi = Axx * i + Axy * j;
mj = Ayx * i + Ayy * j;
*out_gradx++ = _interpolate(x+mi, y+mj, in_gradx);
*out_grady++ = _interpolate(x+mi, y+mj, in_grady);
}
}
/*********************************************************************
* _computeAffineMappedImage
* used only for DEBUG output
*
*/
static void _am_computeAffineMappedImage(
_KLT_FloatImage img, /* images */
float x, float y, /* center of window */
float Axx, float Ayx , float Axy, float Ayy, /* affine mapping */
int width, int height, /* size of window */
_FloatWindow imgdiff) /* output */
{
register int hw = width/2, hh = height/2;
register int i, j;
float mi, mj;
/* Compute values */
for (j = -hh ; j <= hh ; j++)
for (i = -hw ; i <= hw ; i++) {
mi = Axx * i + Axy * j;
mj = Ayx * i + Ayy * j;
*imgdiff++ = _interpolate(x+mi, y+mj, img);
}
}
/*********************************************************************
* _getSubFloatImage
*/
static void _am_getSubFloatImage(
_KLT_FloatImage img, /* image */
float x, float y, /* center of window */
_KLT_FloatImage window) /* output */
{
register int hw = window->ncols/2, hh = window->nrows/2;
int x0 = (int) x;
int y0 = (int) y;
float * windata = window->data;
int offset;
register int i, j;
assert(x0 - hw >= 0);
assert(y0 - hh >= 0);
assert(x0 + hw <= img->ncols);
assert(y0 + hh <= img->nrows);
/* copy values */
for (j = -hh ; j <= hh ; j++)
for (i = -hw ; i <= hw ; i++) {
offset = (j+y0)*img->ncols + (i+x0);
*windata++ = *(img->data+offset);
}
}
/*********************************************************************
* _am_computeIntensityDifferenceAffine
*
* Given two images and the window center in both images,
* aligns the images with the window and computes the difference
* between the two overlaid images using the affine mapping.
* A = [ Axx Axy]
* [ Ayx Ayy]
*/
static void _am_computeIntensityDifferenceAffine(
_KLT_FloatImage img1, /* images */
_KLT_FloatImage img2,
float x1, float y1, /* center of window in 1st img */
float x2, float y2, /* center of window in 2nd img */
float Axx, float Ayx , float Axy, float Ayy, /* affine mapping */
int width, int height, /* size of window */
_FloatWindow imgdiff) /* output */
{
register int hw = width/2, hh = height/2;
float g1, g2;
register int i, j;
float mi, mj;
/* Compute values */
for (j = -hh ; j <= hh ; j++)
for (i = -hw ; i <= hw ; i++) {
g1 = _interpolate(x1+i, y1+j, img1);
mi = Axx * i + Axy * j;
mj = Ayx * i + Ayy * j;
g2 = _interpolate(x2+mi, y2+mj, img2);
*imgdiff++ = g1 - g2;
}
}
/*********************************************************************
* _am_compute6by6GradientMatrix
*
*/
static void _am_compute6by6GradientMatrix(
_FloatWindow gradx,
_FloatWindow grady,
int width, /* size of window */
int height,
float **T) /* return values */
{
register int hw = width/2, hh = height/2;
register int i, j;
float gx, gy, gxx, gxy, gyy, x, y, xx, xy, yy;
/* Set values to zero */
for (j = 0 ; j < 6 ; j++) {
for (i = j ; i < 6 ; i++) {
T[j][i] = 0.0;
}
}
for (j = -hh ; j <= hh ; j++) {
for (i = -hw ; i <= hw ; i++) {
gx = *gradx++;
gy = *grady++;
gxx = gx * gx;
gxy = gx * gy;
gyy = gy * gy;
x = (float) i;
y = (float) j;
xx = x * x;
xy = x * y;
yy = y * y;
T[0][0] += xx * gxx;
T[0][1] += xx * gxy;
T[0][2] += xy * gxx;
T[0][3] += xy * gxy;
T[0][4] += x * gxx;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -