Kanade-Lucas-Tomasi Feature Tracker 程式碼分析
阿新 • • 發佈:2019-02-15
因為研究需要,仔細看了下程式碼,看看有什麼可以利用的地方。
整體來說Kanade-Lucas-Tomasi Feature Tracker的方法就是首先找去特徵點,之後用光流去跟蹤的方法。
上有原始碼,整個的流程跟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三個值的修改。
不對的地方請大家指正。