使用emguCV 3.1.0在图像集合中查找匹配的图像

时间:2016-09-29 08:12:16

标签: c# opencv emgucv flann

我正在开展一个项目,以识别(相似百分比)图像集合中的图像。我使用了EmugCV 3.1.0。代码如下。虽然该程序运行,但它有以下问题

  1. 匹配时找到始终显示第一张图片的百分比。找到附件
  2. enter image description here

    1. 如果我们将dbimage集合中的相同图像作为两次并且与查询图像相同的图像,则所有匹配百分比为零。找到附件

      string [] dbImages = {imgPath +" 1.jpg",imgPath +" 2.jpg",imgPath +" 3.jpg",imgPath + " 4.JPG" };  string queryImage = imgPath +" 4.jpg";

    2. 在这些图像中,图像" 2"和" 4"是相同的

      enter image description here

      代码如下:

          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<IndecesMapping> matches = Match();
                  IOrderedEnumerable<IndecesMapping> orderedMatches = matches.OrderByDescending(match => 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();
              }
      
              /// <summary>
              /// Main method.
              /// </summary>
              static public IList<IndecesMapping> 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<IndecesMapping> imap;
      
                  // compute descriptors for each image
                  var dbDescsList = ComputeMultipleDescriptors(dbImages, out imap);
      
                  // concatenate all DB images descriptors into single Matrix
                  Matrix<float> dbDescs = ConcatDescriptors(dbDescsList);
      
                  // compute descriptors for the query image
                  Matrix<float> queryDescriptors = ComputeSingleDescriptors(queryImage);
      
                  FindMatches(dbDescs, queryDescriptors, ref imap);
      
                  return imap;
              }
      
              /// <summary>
              /// Computes image descriptors.
              /// </summary>
              /// <param name="fileName">Image filename.</param>
              /// <returns>The descriptors for the given image.</returns>
              static public Matrix<float> ComputeSingleDescriptors(string fileName)
              {
                  Matrix<float> descs = null;
                  using (Image<Gray, Byte> img = new Image<Gray, byte>(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<float>(observedDescriptors.Size);
                      detector.Compute(img, keyPoints, descs);
                  }
      
                  return descs;
              }
      
      
              /// <summary>
              /// 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.
              /// </summary>
              /// <param name="fileNames">Filenames of images to process.</param>
              /// <param name="imap">List of IndecesMapping to hold descriptor ranges for each image.</param>
              /// <returns>List of descriptors for the given images.</returns>
              static public IList<Matrix<float>> ComputeMultipleDescriptors(string[] fileNames, out IList<IndecesMapping> imap)
              {
                  imap = new List<IndecesMapping>();
      
                  IList<Matrix<float>> descs = new List<Matrix<float>>();
      
                  int r = 0;
      
                  for (int i = 0; i < 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;
              }
      
      
              /// <summary>
              /// Computes 'similarity' value (IndecesMapping.Similarity) for each image in the collection against our query image.
              /// </summary>
              /// <param name="dbDescriptors">Query image descriptor.</param>
              /// <param name="queryDescriptors">Consolidated db images descriptors.</param>
              /// <param name="images">List of IndecesMapping to hold the 'similarity' value for each image in the collection.</param>
              static public void FindMatches(Matrix<float> dbDescriptors, Matrix<float> queryDescriptors, ref IList<IndecesMapping> imap)
              {
                  var indices = new Matrix<int>(queryDescriptors.Rows, 2); // matrix that will contain indices of the 2-nearest neighbors found
                  var dists = new Matrix<float>(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 < indices.Rows; i++)
                  {
                      // filter out all inadequate pairs based on distance between pairs
                      if (dists.Data[i, 0] < (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 <= i && img.IndexEnd >= i)
                              {
                                  img.Similarity++;
                                  break;
                              }
                          }
                      }
                  }
              }
      
              /// <summary>
              /// Concatenates descriptors from different sources (images) into single matrix.
              /// </summary>
              /// <param name="descriptors">Descriptors to concatenate.</param>
              /// <returns>Concatenated matrix.</returns>
              static public Matrix<float> ConcatDescriptors(IList<Matrix<float>> descriptors)
              {
                  int cols = descriptors[0].Cols;
                  int rows = descriptors.Sum(a => 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<float>(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 + "%";
              }
          }
      

1 个答案:

答案 0 :(得分:0)