I try to combine the FAST algorithm and parts of the SIFT Algorithm to get a fast Solution for Mobile Phones.
The code I created for that works like the following:
- Get Image
- calculate Size for Resize with `src.rows/factor` and `src.cols/factor`where factor = sqrt(2)
- resize Image (INTER_NEAREST) and Blur it with GaussianKernel(5x5)
- Run FAST over the new smaller and blurred Image
- Iterate through every candidate and make a Image Patch (15x15) with the candidate in its origin
- calculate the OrientationHistogram and get the peaks of it.
Here the Code:
rows = src.rows/factor;
cols = src.cols/factor;
resize(src, tmp, Size(rows, cols),0,0,INTER_NEAREST);
GaussianBlur(tmp, dst, Size(5,5),0,0);
FAST(dst, candidates, 0,true);
if(candidates.size() > 0){
for(int i = 0; i < candidates.size(); i++){
if(candidates[i].pt.x > 7 && candidates[i].pt.y > 7){
KeyPoint kpt = candidates[i];
int px = kpt.pt.x -7;
int py = kpt.pt.y -7;
if(px + 15 >= src.cols || py + 15 >= src.rows)
continue;
patch = src(Rect(px,py,15,15));
float scl_octv = kpt.size * 0.5f / (1 << k);
float omax = calcOrientationHist(patch, kpt.pt, cvRound(SIFT_ORI_RADIUS * scl_octv), SIFT_ORI_SIG_FCTR * scl_octv, hist, n);
and the calcOrientationHist function:
static float calcOrientationHist(const Mat& img, Point pt, int radius, float sigma, float* hist, int n){
int i, j, k, len = (radius*2+1)*(radius*2+1);
float expf_scale = -1.f/(2.f * sigma * sigma);
AutoBuffer buf(len*4+n+4);
float *X = buf, *Y = X + len, *Mag = X, *Ori = Y + len, *W = Ori + len;
float* temphist = W + len + 2;
for( i = 0; i < n; i++){
temphist[i] = 0.f;
}
for(i = -radius, k = 0; i <= radius; i++){
int y = pt.y+i;
if( y <= 0 || y >= img.rows -1)
continue;
for(j = - radius; j <= radius; j++){
int x = pt.x + j;
if(x <= 0 || x >= img.cols -1)
continue;
//in opencv sift at
float dx = (float)(img.at(y, x+1) - img.at(y,x-1));
float dy = (float)(img.at(y-1,x) - img.at(y+1,x));
X[k] = dx; Y[k] = dy; W[k] = (i*i + j*j)*expf_scale;
k++;
}
}
len = k;
//compute gradient values, orientations and the weights over the pixel neighborhood
hal::exp32f(W, W, len);
hal::fastAtan2(Y, X, Ori, len, true);
hal::magnitude32f(X, Y, Mag, len);
for( k = 0; k < len; k ++){
int bin = cvRound((n/360.f)+Ori[k]);
if(bin >= n)
bin -=n;
if(bin < 0 )
bin +=n;
temphist[bin] += W[k]*Mag[k];
}
//smooth the histogram
temphist[-1] = temphist[n-1];
temphist[-2] = temphist[n-2];
temphist[n] = temphist[0];
temphist[n+1] = temphist[1];
for(i = 0; i < n; i++){
hist[i] = (temphist[i-2] + temphist[i+2])*(1.f/16.f)+
(temphist[i-1] +temphist[i+1])*(4.f/16.f)+
temphist[i]*(6.f/16.f);
}
float maxval = hist[0];
for(i = 1; i < n; i++)
maxval = std::max(maxval, hist[i]);
return maxval;
}
The Idea for this comes from this [Paper](https://www.icg.tugraz.at/publications/pdf/WAGNER_ISMAR08_NFT.pdf)
The first Steps are running pretty good. But the last one seems to result in **ONLY** 4 Keypoints while I get 220193 Candidates from FAST.
The Code I am using is similar with the code from [calcOrientationHist Function](https://github.com/opencv/opencv_contrib/blob/master/modules/xfeatures2d/src/sift.cpp) from the sift.cpp The Input Image is my Image Patch, the Point is the Candidates Point. To calculate the radius and sigma I needed `scl_octv`but because I dont really go in "Octaves" through the Image I just calculated it like this: `float scl_octv = kpt.size * 0.5f / (1 << 1);`similar to the sift.cpp but with the difference that I add bytewise 1 and not the actual octave. The Peak detection after creating the histogram looks like this:
float mag_thr = (float)(omax * SIFT_ORI_PEAK_RATIO);
for(int j = 0; j < n; j++){
int l = j > 0 ? j - 1 : n -1;
int r2 = j < n-1 ? j+1 : 0;
if(hist[j] > hist[l] && hist[j] > hist[r2] && hist[j] >= mag_thr){
float bin = j + 0.5f * ( hist[i] - hist[r2] ) / ( hist[l] - 2 * hist[j] + hist[r2]);
bin = bin < 0 ? n +bin : bin >= n ? bin - n : bin;
kpt.angle = 360.f - (float)((360.f/n) * bin);
if(std::abs(kpt.angle - 360.f) < FLT_EPSILON)
kpt.angle = 0.f;
features.push_back(kpt);
Where `SIFT_ORI_PEAK_RATIO` is 0.8f.
When I cout the size of features I get the number `4` in the console. The Image I am using for testing is this:

After it is read through `ìmread` I turn it into a grayscale image with `cvtColor(bas, src, CV_BGR2GRAY);`
where `bas` is the loaded Image and `src` the output. In my Example I only go through one Resize and Blur step.
I hope somebody can see why it doesn't work fine.
↧