因为研究需要,仔细看了下代码,看看有什么可以利用的地方。
整体来说Kanade-Lucas-Tomasi Feature Tracker的方法就是首先找去特征点,之后用光流去跟踪的方法。
Opencv中已经有了example,大家可以运行下看效果,同时Homepage:http://www.ces.clemson.edu/~stb/klt/
上有源码,整个的流程跟Opencv差不多。
我们以官网上的原程序中的example1进行分析:(剩下的几个例子整体流程都差不多,仅仅是目的不一样)
首先都是建立两个结构体:
tc = KLTCreateTrackingContext(); KLTPrintTrackingContext(tc); fl = KLTCreateFeatureList(nFeatures);
tc就是跟踪的中用到的一些参数在选特征点的时候也有用到。
fl就是我们说道德特征点了,包括了特征值和特征点在图像中的位置。
之后使用:
KLTSelectGoodFeatures(tc, img1, ncols, nrows, fl);
使用上面的函数选取特征点
KLTTrackFeatures(tc, img1, img2, ncols, nrows, fl);
使用这个函数在img2中寻找对应的特征点。
一次循环就可以实现跟踪了。
那么出现了一个问题:特征点是怎么定义的:
我们分析KLTSelectGoodFeatures这个函数:
函数中又使用了:
_KLTSelectGoodFeatures(tc, img, ncols, nrows, fl, SELECTING_ALL);
这个函数,函数中首先见了了一个pointlist的分量,并分配了内存空间:
pointlist = (int *) malloc(ncols * nrows * 3 * sizeof(int));
为什么要*3呢?其实pointlist中存了图像中点的位置x,y和特征值的大小val。
特征值是什么呢?这个特征是就是对应像素点的梯度值。
{ register float gx, gy; register float gxx, gxy, gyy; register int xx, yy; register int *ptr; float val; unsigned int limit = 1; int borderx = tc->borderx; /* Must not touch cols */ int bordery = tc->bordery; /* lost by convolution */ int x, y; int i; if (borderx < window_hw) borderx = window_hw; if (bordery < window_hh) bordery = window_hh; /* Find largest value of an int */ for (i = 0 ; i < sizeof(int) ; i++) limit *= 256; limit = limit/2 - 1; /* For most of the pixels in the image, do ... */ ptr = pointlist; for (y = bordery ; y < nrows - bordery ; y += tc->nSkippedPixels + 1) for (x = borderx ; x < ncols - borderx ; x += tc->nSkippedPixels + 1) { /* Sum the gradients in the surrounding window */ gxx = 0; gxy = 0; gyy = 0; for (yy = y-window_hh ; yy <= y+window_hh ; yy++) for (xx = x-window_hw ; xx <= x+window_hw ; xx++) { gx = *(gradx->data + ncols*yy+xx); gy = *(grady->data + ncols*yy+xx); gxx += gx * gx; gxy += gx * gy; gyy += gy * gy; } /* Store the trackability of the pixel as the minimum of the two eigenvalues */ *ptr++ = x; *ptr++ = y; val = _minEigenvalue(gxx, gxy, gyy); if (val > limit) { KLTWarning("(_KLTSelectGoodFeatures) minimum eigenvalue %f is " "greater than the capacity of an int; setting " "to maximum value", val); val = (float) limit; } *ptr++ = (int) val; npoints++; }
代码中的特征值取得时每个像素点临域梯度值的加权值。
之后程序来到了函数:
_enforceMinimumDistance( pointlist, npoints, featurelist, ncols, nrows, tc->mindist, tc->min_eigenvalue, overwriteAllFeatures);
这里通过比较每个像素点val和对应阈值的大小来提取特征点:
if (!featuremap[y*ncols+x] && val >= min_eigenvalue) { featurelist->feature[indx]->x = (KLT_locType) x; featurelist->feature[indx]->y = (KLT_locType) y; featurelist->feature[indx]->val = (int) val; featurelist->feature[indx]->aff_img = NULL; featurelist->feature[indx]->aff_img_gradx = NULL; featurelist->feature[indx]->aff_img_grady = NULL; featurelist->feature[indx]->aff_x = -1.0; featurelist->feature[indx]->aff_y = -1.0; featurelist->feature[indx]->aff_Axx = 1.0; featurelist->feature[indx]->aff_Ayx = 0.0; featurelist->feature[indx]->aff_Axy = 0.0; featurelist->feature[indx]->aff_Ayy = 1.0; indx++;
min_eigenvalue就是所使用的阈值,在tc中定义
那么程序的修改,我们需要根据自己的特征对这个阈值进行修改,同时对featurelist进行如上的修改,其实主要还是x,y,val三个值的修改。
不对的地方请大家指正。