2016-03-28 8 views
4

Ich benutze Emgu CV SURF feauture um ähnliche Objekte in Bildern zu erkennen.Emgu CV SURF erhalten Koordinaten der gepaarten Punkte

Das Bild rechts gezogen wird, alle die wichtigsten Punkte gefunden, in beiden Bildern, die ähnlich Punkte (das ist, was ich will) und ein Rechteck (in der Regel Rechteck, manchmal nur eine Zeile), das deckt die ähnliche Punkte.

Das Problem ist, dass die ähnlichen Punkte im Bild zu sehen sind, aber sie sind nicht in dem Format Ich möchte in der Tat gerettet, sie in einem Objekt VectorOfKeyPoint gespeichert sind, die nur einen Zeiger speichert, und andere Speicherdaten, wo die Punkte im Speicher gespeichert sind (das ist, was ich denke). Was bedeutet, kann ich die ähnliche Punkte paarweise wie nicht erhalten:

((img1X, img1Y), (img2X, img2Y))

Dies wäre, was ich suche, so dass ich die Punkte später nutzen kann. Im Moment kann ich nur die Punkte im Ergebnisbild sehen, aber ich kann nicht sie in Paaren bekommen.

Der Code, den ich verwende, ist das Beispiel von Emgu CV.

//---------------------------------------------------------------------------- 
// Copyright (C) 2004-2016 by EMGU Corporation. All rights reserved.  
//---------------------------------------------------------------------------- 
using System; 
using System.Collections.Generic; 
using System.Diagnostics; 
using System.Drawing; 
using System.Runtime.InteropServices; 
using Emgu.CV; 
using Emgu.CV.CvEnum; 
using Emgu.CV.Features2D; 
using Emgu.CV.Structure; 
using Emgu.CV.Util; 
#if !__IOS__ 
using Emgu.CV.Cuda; 
#endif 
using Emgu.CV.XFeatures2D; 

namespace FirstEmgu 
{ 

    public static class DrawMatches 
    { 
    // -------------------------------- 
    // ORIGINAL FUNCTION FROM EXAMPLE 
    // -------------------------------- 
     private static void FindMatch(Mat modelImage, Mat observedImage, out long matchTime, out VectorOfKeyPoint modelKeyPoints, out VectorOfKeyPoint observedKeyPoints, VectorOfVectorOfDMatch matches, out Mat mask, out Mat homography) 
     { 
      int k = 2; 
      double uniquenessThreshold = 0.8; 
      double hessianThresh = 300; 

      Stopwatch watch; 
      homography = null; 

      modelKeyPoints = new VectorOfKeyPoint(); 
      observedKeyPoints = new VectorOfKeyPoint(); 

#if !__IOS__ 
      if (CudaInvoke.HasCuda) 
      { 
       CudaSURF surfCuda = new CudaSURF((float)hessianThresh); 
       using (GpuMat gpuModelImage = new GpuMat(modelImage)) 
       //extract features from the object image 
       using (GpuMat gpuModelKeyPoints = surfCuda.DetectKeyPointsRaw(gpuModelImage, null)) 
       using (GpuMat gpuModelDescriptors = surfCuda.ComputeDescriptorsRaw(gpuModelImage, null, gpuModelKeyPoints)) 
       using (CudaBFMatcher matcher = new CudaBFMatcher(DistanceType.L2)) 
       { 
        surfCuda.DownloadKeypoints(gpuModelKeyPoints, modelKeyPoints); 
        watch = Stopwatch.StartNew(); 

        // extract features from the observed image 
        using (GpuMat gpuObservedImage = new GpuMat(observedImage)) 
        using (GpuMat gpuObservedKeyPoints = surfCuda.DetectKeyPointsRaw(gpuObservedImage, null)) 
        using (GpuMat gpuObservedDescriptors = surfCuda.ComputeDescriptorsRaw(gpuObservedImage, null, gpuObservedKeyPoints)) 
        //using (GpuMat tmp = new GpuMat()) 
        //using (Stream stream = new Stream()) 
        { 
         matcher.KnnMatch(gpuObservedDescriptors, gpuModelDescriptors, matches, k); 

         surfCuda.DownloadKeypoints(gpuObservedKeyPoints, observedKeyPoints); 

         mask = new Mat(matches.Size, 1, DepthType.Cv8U, 1); 
         mask.SetTo(new MCvScalar(255)); 
         Features2DToolbox.VoteForUniqueness(matches, uniquenessThreshold, mask); 

         int nonZeroCount = CvInvoke.CountNonZero(mask); 
         if (nonZeroCount >= 4) 
         { 
          nonZeroCount = Features2DToolbox.VoteForSizeAndOrientation(modelKeyPoints, observedKeyPoints, 
           matches, mask, 1.5, 20); 
          if (nonZeroCount >= 4) 
           homography = Features2DToolbox.GetHomographyMatrixFromMatchedFeatures(modelKeyPoints, 
            observedKeyPoints, matches, mask, 2); 
         } 
        } 
        watch.Stop(); 
       } 
      } 
      else 
#endif 
      { 
       using (UMat uModelImage = modelImage.ToUMat(AccessType.Read)) 
       using (UMat uObservedImage = observedImage.ToUMat(AccessType.Read)) 
       { 
        SURF surfCPU = new SURF(hessianThresh); 
        //extract features from the object image 
        UMat modelDescriptors = new UMat(); 
        surfCPU.DetectAndCompute(uModelImage, null, modelKeyPoints, modelDescriptors, false); 

        watch = Stopwatch.StartNew(); 

        // extract features from the observed image 
        UMat observedDescriptors = new UMat(); 
        surfCPU.DetectAndCompute(uObservedImage, null, observedKeyPoints, observedDescriptors, false); 
        BFMatcher matcher = new BFMatcher(DistanceType.L2); 
        matcher.Add(modelDescriptors); 

        matcher.KnnMatch(observedDescriptors, matches, k, null); 
        mask = new Mat(matches.Size, 1, DepthType.Cv8U, 1); 
        mask.SetTo(new MCvScalar(255)); 
        Features2DToolbox.VoteForUniqueness(matches, uniquenessThreshold, mask); 

        int nonZeroCount = CvInvoke.CountNonZero(mask); 
        if (nonZeroCount >= 4) 
        { 
         nonZeroCount = Features2DToolbox.VoteForSizeAndOrientation(modelKeyPoints, observedKeyPoints, 
          matches, mask, 1.5, 20); 
         if (nonZeroCount >= 4) 
          homography = Features2DToolbox.GetHomographyMatrixFromMatchedFeatures(modelKeyPoints, 
           observedKeyPoints, matches, mask, 2); 
        } 

        watch.Stop(); 
       } 
      } 
      matchTime = watch.ElapsedMilliseconds; 
     } 
     // -------------------------------- 
     // ORIGINAL FUNCTION FROM EXAMPLE 
     // -------------------------------- 
     /// <summary> 
     /// Draw the model image and observed image, the matched features and homography projection. 
     /// </summary> 
     /// <param name="modelImage">The model image</param> 
     /// <param name="observedImage">The observed image</param> 
     /// <param name="matchTime">The output total time for computing the homography matrix.</param> 
     /// <returns>The model image and observed image, the matched features and homography projection.</returns> 
     public static Mat Draw(Mat modelImage, Mat observedImage, out long matchTime) 
     { 
      Mat homography; 
      VectorOfKeyPoint modelKeyPoints; 
      VectorOfKeyPoint observedKeyPoints; 
      using (VectorOfVectorOfDMatch matches = new VectorOfVectorOfDMatch()) 
      { 
       Mat mask; 
       FindMatch(modelImage, observedImage, out matchTime, out modelKeyPoints, out observedKeyPoints, matches, 
        out mask, out homography); 

       //Draw the matched keypoints 
       Mat result = new Mat(); 
       Features2DToolbox.DrawMatches(modelImage, modelKeyPoints, observedImage, observedKeyPoints, 
        matches, result, new MCvScalar(255, 255, 255), new MCvScalar(255, 255, 255), mask); 

       #region draw the projected region on the image 

       if (homography != null) 
       { 
        //draw a rectangle along the projected model 
        Rectangle rect = new Rectangle(Point.Empty, modelImage.Size); 
        PointF[] pts = new PointF[] 
       { 
        new PointF(rect.Left, rect.Bottom), 
        new PointF(rect.Right, rect.Bottom), 
        new PointF(rect.Right, rect.Top), 
        new PointF(rect.Left, rect.Top) 
       }; 
        pts = CvInvoke.PerspectiveTransform(pts, homography); 

        Point[] points = Array.ConvertAll<PointF, Point>(pts, Point.Round); 
        using (VectorOfPoint vp = new VectorOfPoint(points)) 
        { 
         CvInvoke.Polylines(result, vp, true, new MCvScalar(255, 0, 0, 255), 5); 
        } 

       } 

       #endregion 

       return result; 

      } 
     } 

     // ---------------------------------- 
     // WRITTEN BY MYSELF 
     // ---------------------------------- 
     // Returns 4 points (usually rectangle) of similar points 
     // but can't be used, since sometimes this is a line (negative 
     // points) 
     public static Point[] FindPoints(Mat modelImage, Mat observedImage, out long matchTime) 
     { 
      Mat homography; 
      VectorOfKeyPoint modelKeyPoints; 
      VectorOfKeyPoint observedKeyPoints; 
      using (VectorOfVectorOfDMatch matches = new VectorOfVectorOfDMatch()) 
      { 
       Mat mask; 
       FindMatch(modelImage, observedImage, out matchTime, out modelKeyPoints, out observedKeyPoints, matches, 
        out mask, out homography); 

       //Draw the matched keypoints 
       Mat result = new Mat(); 
       Features2DToolbox.DrawMatches(modelImage, modelKeyPoints, observedImage, observedKeyPoints, 
        matches, result, new MCvScalar(255, 255, 255), new MCvScalar(255, 255, 255), mask); 

       Point[] points = null; 
       if (homography != null) 
       { 
        //draw a rectangle along the projected model 
        Rectangle rect = new Rectangle(Point.Empty, modelImage.Size); 
        PointF[] pts = new PointF[] 
       { 
        new PointF(rect.Left, rect.Bottom), 
        new PointF(rect.Right, rect.Bottom), 
        new PointF(rect.Right, rect.Top), 
        new PointF(rect.Left, rect.Top) 
       }; 
        pts = CvInvoke.PerspectiveTransform(pts, homography); 

        points = Array.ConvertAll<PointF, Point>(pts, Point.Round); 

       } 

       return points; 
      } 
     } 
    } 
} 

EDIT

Ich habe es geschafft, einige Punkte aus den Spielen zu bekommen Objekte wie folgt aus:

Features2DToolbox.DrawMatches(modelImage, modelKeyPoints, observedImage, observedKeyPoints, 
        matches, result, new MCvScalar(255, 255, 255), new MCvScalar(255, 255, 255), mask); 

       for (int i = 0; i < matches.Size; i++) 
       { 
        var a = matches[i].ToArray(); 
        foreach (var e in a) 
        { 
         Point p = new Point(e.TrainIdx, e.QueryIdx); 
         Console.WriteLine(string.Format("Point: {0}", p)); 
        } 
        Console.WriteLine("-----------------------"); 
       } 

Ich denke, das mir die Punkte bekommen sollte. Ich habe es geschafft, es in Python arbeiten zu lassen, und der Code ist nicht sehr unterschiedlich. Problem ist, dass zu viele Punkte zurückgegeben werden. In der Tat, diese liefert mir alle Punkte auf Y.

Beispiel

(45, 1), (67, 1)

(656, 2), (77, 2)

...

Es bringt mir nicht die Punkte, die ich will, auch wenn ich in der Nähe sein könnte. Irgendwelche Vorschläge werden geschätzt.

EDIT 2 Diese Frage: Find interest point in surf Detector Algorithm ist etwas sehr ähnlich zu dem, was ich brauche. Es gibt nur eine Antwort, aber es sagt nicht, wie man die Koordinaten der abgeglichenen Punkte erhält. Das ist was ich brauche, wenn es in beiden Bildern ein Objekt gibt, holen Sie sich die Koordinaten der Objektpunkte aus beiden Bildern.

Antwort

2

In der Funktion FindMatch wird jedes Punktpaar durch die Funktion VoteForUniqueness validiert. Das Ergebnis dieser Validierung wird in mask gespeichert.

Also alles, was Sie tun müssen, ist zu überprüfen, ob das Spiel oder nicht validiert:

for (int i = 0; i < matches.Size; i++) 
{ 
    var a = matches[i].ToArray(); 
    if (mask.GetData(i)[0] == 0) 
     continue; 
    foreach (var e in a) 
    { 
     Point p = new Point(e.TrainIdx, e.QueryIdx); 
     Console.WriteLine(string.Format("Point: {0}", p)); 
    } 
    Console.WriteLine("-----------------------"); 
} 
3

Die Koordinaten nicht von TrainIdx und QueryIdx gemacht wird, sind die Indizes der keypoints. Dies ergibt die Pixelkoordinaten, die zwischen dem Modell und dem beobachteten Bild übereinstimmen.

for (int i = 0; i < matches.Size; i++) 
{ 
    var arrayOfMatches = matches[i].ToArray(); 
    if (mask.GetData(i)[0] == 0) continue; 
    foreach (var match in arrayOfMatches) 
    { 
     var matchingModelKeyPoint = modelKeyPoints[match.TrainIdx]; 
     var matchingObservedKeyPoint = observedKeyPoints[match.QueryIdx]; 
     Console.WriteLine("Model coordinate '" + matchingModelKeyPoint.Point + "' matches observed coordinate '" + matchingObservedKeyPoint.Point + "'."); 
    } 
} 

Die Anzahl der Elemente in arrayOfMatches gleich dem Wert von K. Es ist mein Verständnis ist, dass das Spiel mit dem geringsten Abstand die beste ist.

Verwandte Themen