SURF matching against a database of images
I'd like to compare an image taken with a webcam against a database of known images. I've been trying to use SURF for this, and it works OK when the number of images is small. Using BruteForceMatcher i get good, repeatable results although it is very slow, since I need to compare against a database of 3000 images, which would take several minutes.
A post in stackoverflow led me to a paper where they say using a FLANN index of the images is very, very fast (down to a few milliseconds for thousands of images). A poster in that thread says he uses a big FLANN index with the SURF features of all images, and uses this to compare to the current image. I've tried to do what he claims. I'm using EMGU to acces openCV from C#. What I get is a Matrix<float> of image features for each image, and i concatenate all the matrices to get a big matrix of all features. WIth this i I build a FLANN index and use this to compare the current observation against this big database with KnnMatch.
It returns in about 25ms with all rows with value zero.
Now, if i reverse this, and build the FLANN index with the points of the observed image and compare the big bad matrix of all features, for 100 images it takes about 300ms and it works.
Has anyone tried this approach with success? Is it even possible to do this with opencv?
Thanks
EDIT: Added code of comments
What I'm doing currently is the following:
Part 1: initialization
Read all the images in a directory, use
surfCPU.ComputeDescriptorsRaw
and
surfCPU.DetectKeyPointsRaw (btw: SURFDetector surfCPU = new SURFDetector(500, false);)
for each DetectKeypoints, load into a big matrix:
supermatrix = surfCPU.ComputeDescriptorsRaw(img, null, add.modelKeyPoints);
also keep a List<int> of KeypointIndices:
imageLastIndex.Add(supermatrix.Rows); (assuming each image has 100 points: 100, 200,300: image 0 is points 0 to 99, image 2 is points 100 to 199, etc)
once all the images have been analyzed, build the index:
Emgu.CV.Flann.Index fln = new Index(supermatrix,4);
Part 2:
query Matrix<int> indices = new Matrix<int>(supermatrix.Rows, k);
Matrix<float> dist = new Matrix<float>(supermatrix.Rows, k);
fln.KnnSearch(observedDescriptors,indices,dist,k,12);
the result here is that "dist" (the return value) Is a Matrix<float> filled with all rows and cols with value "0.0"
Now if I do the opposite (notice the FLANN is created with observedDescriptors which is N times smaller than supermatrix, with N=number of images):
Emgu.CV.Flann.Index fln = new Index(observedDescriptors,4);
Matrix<int> indices = new Matrix<int>(supermatrix.Rows, k);
Matrix<float> dist = new Matrix<float>(supermatrix.Rows, k);
fln.KnnSearch(supermatrix, indices,dist, k,12);
the result is correct, but the FLANN index is not really "exploited". also this is slower than linear search
I am trying to do the same. Did any of you succeed to set this up.
Is there any github source that I can take a look at it ?