2016-09-29 2 views
1

Je travaille sur un projet pour reconnaître (pourcentage de similarité) une image à partir d'une collection d'images. J'ai utilisé l'EmugCV 3.1.0. Les codes sont donnés ci-dessous. Bien que le programme fonctionne, il ont des problèmes suivantsTrouver l'image correspondante dans une collection d'images en utilisant emguCV 3.1.0

  1. Lorsque le pourcentage trouvé matchs montrant toujours pour la première image. Trouvez la pièce jointe

enter image description here

  1. si nous mettons la même image dans la collection de dbimage comme deux fois et cette même image que l'image de requête, le tout pourcentage correspondant est égal à zéro. trouver la pièce jointe

    chaîne [] dbImages = {imgPath + "1.jpg", imgPath + "2.jpg", imgPath + "3.jpg", imgPath + "4.jpg"}; chaîne queryImage = imgPath + "4.jpg";

Dans ces images images "2" et "4" sont les mêmes

enter image description here

Les codes sont donnés ci-dessous

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 + "%"; 
     } 
    } 

Répondre