2016-03-28 21 views
4

私はEmgu CVのSURF機能を使用して、画像内の同様のオブジェクトを認識しています。Emgu CV SURF一致する点の座標を取得

画像は、両方の画像、(私が欲しいものです同様のポイントとカバー長方形(通常は四角形、時々ちょうどライン)で、見つかったすべての重要なポイントを示し、右描かれています同様の点。

問題が同様のポイントが画像で見られているが、それらは私が望む形式で保存されていないことを、実際に、彼らはただのポインタを格納VectorOfKeyPointオブジェクトに格納しているされ、とポイントがメモリに格納されている他のメモリデータ(これは私が思う)です。つまり、私のようなペアで同様のポイントにを取得することはできません。

((img1X、img1Y)、(img2X、img2Y))

これには、私が探しているものをだろう私は後でポイントを使用することができます。 今、結果の画像にポイントが表示されるだけですが、 をペアで取得することはできません。

私が使用しているコードは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

私はこのような一致オブジェクトのうち、いくつかのポイントを得ることができた:

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("-----------------------"); 
       } 

私はこれが私のポイントを得るべきだと思います。私はそれをPythonで動作させることができましたが、コードはそれほど違いはありません。問題は、返されるポイントが多すぎるということです。実際には、これは私Y.上のすべての点を返す

(45、1)、(67、1)

(656、2)、(77、2)

...

私は近くにいるかもしれないが、私が望むポイントは得られない。どんな提案も感謝しています。

EDIT 2 この質問:Find interest point in surf Detector Algorithmは私が必要なものと非常によく似たものです。答えは1つだけですが、マッチしたポイントの座標を取得する方法はわかりません。それは私が必要なものです。両方の画像にオブジェクトがある場合は、両方の画像からオブジェクト点の座標を取得します。

答えて

2

FindMatch関数では、ポイントの各ペアは、関数VoteForUniquenessによって検証されます。この検証の結果はmaskに格納されます。

だから、あなたがしなければならないすべては一致が検証されているかどうか確認している:

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

座標がTrainIdxとQueryIdxで作られていない、これらは、キーポイントのインデックスです。これにより、モデルと観測画像の間で一致するピクセル座標が得られます。

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 + "'."); 
    } 
} 

arrayOfMatches内の項目数は、それは最低の距離とのマッチが最善であるというのが私の理解であるKの値に等しいです。

関連する問題