title: Using custom distance function with FLANN or Knn in OpenCv?
body: <p>I'm working on code that computes dense SIFT features from a set of images, based on SIFT flow: <a href="http://people.csail.mit.edu/celiu/SIFTflow/" rel="nofollow">http://people.csail.mit.edu/celiu/SIFTflow/</a></p>
  
  <p>I'd like to try building a FLANN index on these images by comparing the "energy" between each image in SIFT flow representation.</p>
  
  <p>I have the code to compute the energy from here: <a href="http://richardt.name/publications/video-deanaglyph/" rel="nofollow">http://richardt.name/publications/video-deanaglyph/</a></p>
  
  <p>Is there a way to create my own distance function for the indexing?</p>
  
  <hr>
  
  <p>RELATED NOTE:</p>
  
  <p>I was <strong>finally</strong> able to get an alternate (but not custom) distance function working with flann::Index.  The trick is you need to use flann::GenericIndex like so: </p>
  
  <p><code>flann::GenericIndex&lt;cvflann::ChiSquareDistance&lt;int&gt;&gt; flannIndex(descriptors, cvflann::KDTreeIndexParams());</code></p>
  
  <p>But you need to give it <strong>CV_32S</strong> descriptors.  </p>
  
  <p>And if you use knnSearch with custom distance function, you have to provide a <strong>CV_32S</strong> results Mat and <strong>CV_32F</strong> distances Mat.</p>
  
  <p>Here's my full code in case it's helpful (not a lot of documentation out there):</p>
  
  <pre><code>    Mat samples;
      loadDescriptors(samples); // loading descriptors from .yml file
  
      samples *= 100000; // scaling up my descriptors to be int
      samples.convertTo(samples, CV_32S); // convert float to int
  
      // create flann index
      flann::GenericIndex&lt;cvflann::ChiSquareDistance&lt;int&gt;&gt; flannIndex(samples, cvflann::KDTreeIndexParams());
      // NOTE lack of distance type in constructor parameters
      // (unlike flann::index)
  
      // now try knnSearch 
  
      int k=10; // find 10 nearest neighbors
  
      Mat results(1,10,CV_32S), dists(1,10,CV_32F);
      // (1,10) Mats for the output, types CV_32S and CV_32F
  
      Mat responseHistogram;
      responseHistogram = samples.row(60); 
      // choose a random row from the descriptors Mat
      // to find nearest neighbors
  
      flannIndex.knnSearch(responseHist, results, dists, k, cvflann::SearchParams(200) );
  
      cout &lt;&lt; results &lt;&lt; endl;
      cout &lt;&lt; dists &lt;&lt; endl;
  
      flannIndex.save(ofToDataPath("indexChi2.txt"));
  </code></pre>
  
  <p>Using Chi Squared actually seems to work better for me than L2 distance.  My feature vectors are BoW histograms in this case.</p>