title: Finding matching image within a collection of images using emguCV 3.1.0
body: <p>I'm working on a project to recognize (similarity percentage) a image from a collection of image. I used the EmugCV 3.1.0. The codes are given below. Although the program runs, it have following issues</p>
  
  <ol>
  <li>When matches found the percentage showing always for first image. Find the attachment</li>
  </ol>
  
  <p><a href="https://i.stack.imgur.com/tpGhI.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/tpGhI.png" alt="enter image description here"></a></p>
  
  <ol start="2">
  <li><p>if we put the same image in dbimage collection as twice and this same image as query image, the all matching percentage is zero. find the attachment </p>
  
  <p>string[] dbImages = { imgPath + "1.jpg", imgPath + "2.jpg", imgPath + "3.jpg", imgPath + "4.jpg" };
   string queryImage = imgPath + "4.jpg";</p></li>
  </ol>
  
  <p>In these images image "2" and "4" are same</p>
  
  <p><a href="https://i.stack.imgur.com/QOgyE.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/QOgyE.png" alt="enter image description here"></a></p>
  
  <p>The codes are given below</p>
  
  <pre><code>    public partial class Form1 : Form
      {
          private static double surfHessianThresh = 300;
          private static SURF detector;
          public Form1()
          {
              InitializeComponent();
              ImageMatching();
          }
  
          public void ImageMatching()
          {
              string MatchString = null;
              detector = new SURF(surfHessianThresh);
              IList&lt;IndecesMapping&gt; matches = Match();
              IOrderedEnumerable&lt;IndecesMapping&gt; orderedMatches = matches.OrderByDescending(match =&gt; match.Similarity);
  
              foreach (IndecesMapping match in orderedMatches)
              {
                  MatchString = MatchString + "\n" + match.ToString();
              }
              lblMatch.Text = MatchString;
              //Console.WriteLine();
              //Console.WriteLine("MOST LIKELY MATCH: " + orderedMatches.First());
  
              //Console.WriteLine("Press enter to exit...");
              //Console.ReadLine();
          }
  
          /// &lt;summary&gt;
          /// Main method.
          /// &lt;/summary&gt;
          static public IList&lt;IndecesMapping&gt; Match()
          {
  
              string imgPath = "E:\\Riyas\\Projects\\Image Recognition\\Sample Projects\\EmguSample3.1.0\\EmguSample3.1.0\\";
              string[] dbImages = { imgPath + "1.jpg", imgPath + "2.jpg", imgPath + "3.jpg", imgPath + "4.jpg" };
              string queryImage = imgPath + "1.jpg";
  
              IList&lt;IndecesMapping&gt; imap;
  
              // compute descriptors for each image
              var dbDescsList = ComputeMultipleDescriptors(dbImages, out imap);
  
              // concatenate all DB images descriptors into single Matrix
              Matrix&lt;float&gt; dbDescs = ConcatDescriptors(dbDescsList);
  
              // compute descriptors for the query image
              Matrix&lt;float&gt; queryDescriptors = ComputeSingleDescriptors(queryImage);
  
              FindMatches(dbDescs, queryDescriptors, ref imap);
  
              return imap;
          }
  
          /// &lt;summary&gt;
          /// Computes image descriptors.
          /// &lt;/summary&gt;
          /// &lt;param name="fileName"&gt;Image filename.&lt;/param&gt;
          /// &lt;returns&gt;The descriptors for the given image.&lt;/returns&gt;
          static public Matrix&lt;float&gt; ComputeSingleDescriptors(string fileName)
          {
              Matrix&lt;float&gt; descs = null;
              using (Image&lt;Gray, Byte&gt; img = new Image&lt;Gray, byte&gt;(fileName))
              {
                  MKeyPoint[] mkeyPoints = detector.Detect(img, null);
                  VectorOfKeyPoint keyPoints = new VectorOfKeyPoint();
                  keyPoints.Push(mkeyPoints);
  
                  UMat observedDescriptors = new UMat();
                  detector.Compute(img, keyPoints, observedDescriptors);
                  descs = new Matrix&lt;float&gt;(observedDescriptors.Size);
                  detector.Compute(img, keyPoints, descs);
              }
  
              return descs;
          }
  
  
          /// &lt;summary&gt;
          /// Convenience method for computing descriptors for multiple images.
          /// On return imap is filled with structures specifying which descriptor ranges in the concatenated matrix belong to what image.
          /// &lt;/summary&gt;
          /// &lt;param name="fileNames"&gt;Filenames of images to process.&lt;/param&gt;
          /// &lt;param name="imap"&gt;List of IndecesMapping to hold descriptor ranges for each image.&lt;/param&gt;
          /// &lt;returns&gt;List of descriptors for the given images.&lt;/returns&gt;
          static public IList&lt;Matrix&lt;float&gt;&gt; ComputeMultipleDescriptors(string[] fileNames, out IList&lt;IndecesMapping&gt; imap)
          {
              imap = new List&lt;IndecesMapping&gt;();
  
              IList&lt;Matrix&lt;float&gt;&gt; descs = new List&lt;Matrix&lt;float&gt;&gt;();
  
              int r = 0;
  
              for (int i = 0; i &lt; fileNames.Length; i++)
              {
                  var desc = ComputeSingleDescriptors(fileNames[i]);
                  descs.Add(desc);
  
                  imap.Add(new IndecesMapping()
                  {
                      fileName = fileNames[i],
                      IndexStart = r,
                      IndexEnd = r + desc.Rows - 1
                  });
  
                  r += desc.Rows;
              }
  
              return descs;
          }
  
  
          /// &lt;summary&gt;
          /// Computes 'similarity' value (IndecesMapping.Similarity) for each image in the collection against our query image.
          /// &lt;/summary&gt;
          /// &lt;param name="dbDescriptors"&gt;Query image descriptor.&lt;/param&gt;
          /// &lt;param name="queryDescriptors"&gt;Consolidated db images descriptors.&lt;/param&gt;
          /// &lt;param name="images"&gt;List of IndecesMapping to hold the 'similarity' value for each image in the collection.&lt;/param&gt;
          static public void FindMatches(Matrix&lt;float&gt; dbDescriptors, Matrix&lt;float&gt; queryDescriptors, ref IList&lt;IndecesMapping&gt; imap)
          {
              var indices = new Matrix&lt;int&gt;(queryDescriptors.Rows, 2); // matrix that will contain indices of the 2-nearest neighbors found
              var dists = new Matrix&lt;float&gt;(queryDescriptors.Rows, 2); // matrix that will contain distances to the 2-nearest neighbors found
  
              // create FLANN index with 4 kd-trees and perform KNN search over it look for 2 nearest neighbours
              KdTreeIndexParamses kdparam = new KdTreeIndexParamses(4);
  
              var flannIndex = new Index(dbDescriptors, kdparam);
              flannIndex.KnnSearch(queryDescriptors, indices, dists, 2, 24);
  
              for (int i = 0; i &lt; indices.Rows; i++)
              {
                  // filter out all inadequate pairs based on distance between pairs
                  if (dists.Data[i, 0] &lt; (0.6 * dists.Data[i, 1]))
                  {
                      // find image from the db to which current descriptor range belongs and increment similarity value.
                      // in the actual implementation this should be done differently as it's not very efficient for large image collections.
                      foreach (var img in imap)
                      {
                          if (img.IndexStart &lt;= i &amp;&amp; img.IndexEnd &gt;= i)
                          {
                              img.Similarity++;
                              break;
                          }
                      }
                  }
              }
          }
  
          /// &lt;summary&gt;
          /// Concatenates descriptors from different sources (images) into single matrix.
          /// &lt;/summary&gt;
          /// &lt;param name="descriptors"&gt;Descriptors to concatenate.&lt;/param&gt;
          /// &lt;returns&gt;Concatenated matrix.&lt;/returns&gt;
          static public Matrix&lt;float&gt; ConcatDescriptors(IList&lt;Matrix&lt;float&gt;&gt; descriptors)
          {
              int cols = descriptors[0].Cols;
              int rows = descriptors.Sum(a =&gt; a.Rows);
  
              float[,] concatedDescs = new float[rows, cols];
  
              int offset = 0;
  
              foreach (var descriptor in descriptors)
              {
                  // append new descriptors
                  Buffer.BlockCopy(descriptor.ManagedArray, 0, concatedDescs, offset, sizeof(float) * descriptor.ManagedArray.Length);
                  offset += sizeof(float) * descriptor.ManagedArray.Length;
              }
  
              return new Matrix&lt;float&gt;(concatedDescs);
          }
      }
  
      public class IndecesMapping
      {
          public int IndexStart { get; set; }
          public int IndexEnd { get; set; }
          public int Similarity { get; set; }
          public string fileName { get; set; }
  
          public override string ToString()
          {
              return fileName + ": " + Similarity + "%";
          }
      }
  </code></pre>