Forums - KDTrees for Image Matching

2 posts / 0 new
Last post
KDTrees for Image Matching
katrin
Join Date: 28 Oct 11
Posts: 14
Posted: Mon, 2012-07-16 08:51

Hi everyone,

In my current application I have implemented a brute force descriptor matcher to get correspondences between 2 images, using fcvSumOfSquaredDiffs36xNs8. Since there are KDTrees supported within the new FastCV version I would like to implement a matcher using these KDTrees and kNN for better runtime performance.

I've implemented my first approach with kdtrees similar to the brute force approach, but my computed correspondences seem to be wrong (I don't get a correct homography, but I did get one with my brute force algorithm). What would be the correct way? As the code below shows, I'm creating a kdTree from the descriptors of the feature points of my target image. Then I loop over my reference image descriptors and query for the nearest neighbor within the kdTree. I'm only searching for 2 nearest neighbors (maxNN), since I only need the best match as correspondence and the second best match for a ratio test to reject outliers. I'm not sure how to set the other parameters, such as maxDist and maxChecks. Is my approach wrong? If yes, what would be the correct way and what would be good values for maxDist and maxChecks?

float32_t* invLenB = (float32_t*)fcvMemAlloc(state.numCorners*sizeof(float32_t), 16);
int8_t **descriptorsB = (int8_t **) fcvMemAlloc(state.numCorners * sizeof(int8_t *), 16);

for (uint32_t i = 0; i < state.numCorners; i++) {
	descriptorsB[i] = state.imageFeatureBuf[i].descriptor;
	invLenB[i] = (float)(1/sqrt((float)state.imageFeatureBuf[i].normSq));
}

fcvKDTreeDatas8f32* kdTree;
fcvKDTreeCreate36s8f32(*descriptorsB, invLenB, state.numCorners, &kdTree);

int maxNN = 2;
for(int k = 0; k < state.numCornersReferenceImg; k++){
	int32_t numFound;
	int32_t* indicesFound = (int32_t*)fcvMemAlloc(maxNN*sizeof(int32_t), 8);
	float32_t* distancesFound = (float32_t*)fcvMemAlloc(maxNN*sizeof(float32_t), 8);

	fcvFeatureType feature = state.referenceFeatureBuf[k];
	float invLen = (float)(1/sqrt((float)feature.normSq));

	fcvKDTreeQuery36s8f32(kdTree, feature.descriptor, invLen, maxNN, 0.1, 200, NULL, &numFound, indicesFound, distancesFound);

	if(numFound >0){
		int correspondenceIdx = indicesFound[0];
		fcvFeatureType correspondenceFeature = state.imageFeatureBuf[correspondenceIdx];
	}
}

  • Up0
  • Down0
Gary_McGrath
Join Date: 23 Oct 11
Posts: 13
Posted: Mon, 2012-07-23 12:30

Normal 0 false false false EN-US X-NONE X-NONE MicrosoftInternetExplorer4  

 

Assume that your target descriptors and their inverse lengths are in buffers declared as

   int8_t* vectors;

   float32_t* vecInvLen;

and their number is numDescriptorsDB. Somewhere in your program you have to have to initialize kdtree for these target descriptors

   fcvKDTreeDatas8f32* kdTree = 0;

   int err = fcvKDTreeCreate36s8f32( vectors, vecInvLen, numDescriptorsDB, &kdTree );

Now, assume that you extracted numQueries descriptors from camera frame and they are stored

in buffers like below: 

   int8_t* queries;

   float32_t* queryInvLen;

Assume you want numNN (NN – nearest neighbor)results for each query so you declare buffers for them

  int32_t* foundInds;

   float32_t* foundDists;

   int32_t numFound = 0;

I am not going into details how the above pointers are initialiazed, whether they point to static arrays or dynamically allocated blocks. They must point to buffers big enough to accept numNN indices and distances. Now we search for NNS say for i-th query

   err = fcvKDTreeQuery36s8f32( kdTree, queries[ i ], queryInvLen[ i ], numNN, 0.1f, 32, 0, &numFound, foundInds, foundDists );

0.1 is max distance allowed between query and its NN. Number of NNs will be returned in numFound, indices to NNs (referring to vectors array) and distances to NNs will be returned in foundInds and foundDists respectively.

 Once you do not need kdtree anymore you may destroy it

    err = fcvKDTreeDestroy36s8f32( kdTree );

So, basically the usage of kdtree involves just 3 function calls (creation, querying and destruction).

  • Up0
  • Down0
or Register

Opinions expressed in the content posted here are the personal opinions of the original authors, and do not necessarily reflect those of Qualcomm Incorporated or its subsidiaries (“Qualcomm”). The content is provided for informational purposes only and is not meant to be an endorsement or representation by Qualcomm or any other party. This site may also provide links or references to non-Qualcomm sites and resources. Qualcomm makes no representations, warranties, or other commitments whatsoever about any non-Qualcomm sites or third-party resources that may be referenced, accessible from, or linked to this site.