转自 : http://blog.csdn.net/dreamd1987/article/details/7907437
因为研究需要,仔细看了下代码,看看有什么可以利用的地方。
整体来说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三个值的修改。
不对的地方请大家指正。