溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

C#中OpenCvSharp 通過特征點匹配圖片的方法

發布時間:2020-08-24 21:57:35 來源:腳本之家 閱讀:630 作者:StupidsCat 欄目:編程語言

現在的手游基本都是重復操作,一個動作要等好久,結束之后繼續另一個動作.很麻煩,所以動起了自己寫一個游戲輔助的心思.

這個輔助本身沒什么難度,就是通過不斷的截圖,然后從這個截圖中找出預先截好的能代表相應動作的按鈕或者觸發條件的小圖.

找到之后獲取該子區域的左上角坐標,然后通過windows API調用鼠標或者鍵盤做操作就行了.

這里面最難的也就是找圖了,因為要精準找圖,而且最好能適應不同的分辨率下找圖,所以在模板匹配的基礎上,就有了SIFT和SURF的特征點找圖方式.

在寫的過程中查找資料,大都是C++ 或者python的, 很少有原生的C#實現, 所以我就直接拿來翻譯過來了(稍作改動).

SIFT算法

public static Bitmap MatchPicBySift(Bitmap imgSrc, Bitmap imgSub)
    {
      using (Mat matSrc = imgSrc.ToMat())
      using (Mat matTo = imgSub.ToMat())
      using (Mat matSrcRet = new Mat())
      using (Mat matToRet = new Mat())
      {
        KeyPoint[] keyPointsSrc, keyPointsTo;
        using (var sift = OpenCvSharp.XFeatures2D.SIFT.Create())
        {
          sift.DetectAndCompute(matSrc, null, out keyPointsSrc, matSrcRet);
          sift.DetectAndCompute(matTo, null, out keyPointsTo, matToRet);
        }
        using (var bfMatcher = new OpenCvSharp.BFMatcher())
        {
          var matches = bfMatcher.KnnMatch(matSrcRet, matToRet, k: 2);
          var pointsSrc = new List<Point2f>();
          var pointsDst = new List<Point2f>();
          var goodMatches = new List<DMatch>();
          foreach (DMatch[] items in matches.Where(x => x.Length > 1))
          {
            if (items[0].Distance < 0.5 * items[1].Distance)
            {
              pointsSrc.Add(keyPointsSrc[items[0].QueryIdx].Pt);
              pointsDst.Add(keyPointsTo[items[0].TrainIdx].Pt);
              goodMatches.Add(items[0]);
              Console.WriteLine($"{keyPointsSrc[items[0].QueryIdx].Pt.X}, {keyPointsSrc[items[0].QueryIdx].Pt.Y}");
            }
          }
          var outMat = new Mat();
          // 算法RANSAC對匹配的結果做過濾
          var pSrc = pointsSrc.ConvertAll(Point2fToPoint2d);
          var pDst = pointsDst.ConvertAll(Point2fToPoint2d);
          var outMask = new Mat();
          // 如果原始的匹配結果為空, 則跳過過濾步驟
          if (pSrc.Count > 0 && pDst.Count > 0)
            Cv2.FindHomography(pSrc, pDst, HomographyMethods.Ransac, mask: outMask);
          // 如果通過RANSAC處理后的匹配點大于10個,才應用過濾. 否則使用原始的匹配點結果(匹配點過少的時候通過RANSAC處理后,可能會得到0個匹配點的結果).
          if (outMask.Rows > 10)
          {
            byte[] maskBytes = new byte[outMask.Rows * outMask.Cols];
            outMask.GetArray(0, 0, maskBytes);
            Cv2.DrawMatches(matSrc, keyPointsSrc, matTo, keyPointsTo, goodMatches, outMat, matchesMask: maskBytes, flags: DrawMatchesFlags.NotDrawSinglePoints);
          }
          else
            Cv2.DrawMatches(matSrc, keyPointsSrc, matTo, keyPointsTo, goodMatches, outMat, flags: DrawMatchesFlags.NotDrawSinglePoints);
          return OpenCvSharp.Extensions.BitmapConverter.ToBitmap(outMat);
        }
      }
    }

SURF算法

public static Bitmap MatchPicBySurf(Bitmap imgSrc, Bitmap imgSub, double threshold = 400)
    {
      using (Mat matSrc = imgSrc.ToMat())
      using (Mat matTo = imgSub.ToMat())
      using (Mat matSrcRet = new Mat())
      using (Mat matToRet = new Mat())
      {
        KeyPoint[] keyPointsSrc, keyPointsTo;
        using (var surf = OpenCvSharp.XFeatures2D.SURF.Create(threshold,4,3,true,true))
        {
          surf.DetectAndCompute(matSrc, null, out keyPointsSrc, matSrcRet);
          surf.DetectAndCompute(matTo, null, out keyPointsTo, matToRet);
        }
        using (var flnMatcher = new OpenCvSharp.FlannBasedMatcher())
        {
          var matches = flnMatcher.Match(matSrcRet, matToRet);
          //求最小最大距離
          double minDistance = 1000;//反向逼近
          double maxDistance = 0;
          for (int i = 0; i < matSrcRet.Rows; i++)
          {
            double distance = matches[i].Distance;
            if (distance > maxDistance)
            {
              maxDistance = distance;
            }
            if (distance < minDistance)
            {
              minDistance = distance;
            }
          }
          Console.WriteLine($"max distance : {maxDistance}");
          Console.WriteLine($"min distance : {minDistance}");
          var pointsSrc = new List<Point2f>();
          var pointsDst = new List<Point2f>();
          //篩選較好的匹配點
          var goodMatches = new List<DMatch>();
          for (int i = 0; i < matSrcRet.Rows; i++)
          {
            double distance = matches[i].Distance;
            if (distance < Math.Max(minDistance * 2, 0.02))
            {
              pointsSrc.Add(keyPointsSrc[matches[i].QueryIdx].Pt);
              pointsDst.Add(keyPointsTo[matches[i].TrainIdx].Pt);
              //距離小于范圍的壓入新的DMatch
              goodMatches.Add(matches[i]);
            }
          }
          var outMat = new Mat();
          // 算法RANSAC對匹配的結果做過濾
          var pSrc = pointsSrc.ConvertAll(Point2fToPoint2d);
          var pDst = pointsDst.ConvertAll(Point2fToPoint2d);
          var outMask = new Mat();
          // 如果原始的匹配結果為空, 則跳過過濾步驟
          if (pSrc.Count > 0 && pDst.Count > 0)
            Cv2.FindHomography(pSrc, pDst, HomographyMethods.Ransac, mask: outMask);
          // 如果通過RANSAC處理后的匹配點大于10個,才應用過濾. 否則使用原始的匹配點結果(匹配點過少的時候通過RANSAC處理后,可能會得到0個匹配點的結果).
          if (outMask.Rows > 10)
          {
            byte[] maskBytes = new byte[outMask.Rows * outMask.Cols];
            outMask.GetArray(0, 0, maskBytes);
            Cv2.DrawMatches(matSrc, keyPointsSrc, matTo, keyPointsTo, goodMatches, outMat, matchesMask: maskBytes, flags: DrawMatchesFlags.NotDrawSinglePoints);
          }
          else
            Cv2.DrawMatches(matSrc, keyPointsSrc, matTo, keyPointsTo, goodMatches, outMat, flags: DrawMatchesFlags.NotDrawSinglePoints);
          return OpenCvSharp.Extensions.BitmapConverter.ToBitmap(outMat);
        }
      }
    }

C#中OpenCvSharp 通過特征點匹配圖片的方法

模板匹配

 public static System.Drawing.Point FindPicFromImage(Bitmap imgSrc, Bitmap imgSub, double threshold = 0.9)
    {
      OpenCvSharp.Mat srcMat = null;
      OpenCvSharp.Mat dstMat = null;
      OpenCvSharp.OutputArray outArray = null;
      try
      {
        srcMat = imgSrc.ToMat();
        dstMat = imgSub.ToMat();
        outArray = OpenCvSharp.OutputArray.Create(srcMat);
        OpenCvSharp.Cv2.MatchTemplate(srcMat, dstMat, outArray, Common.templateMatchModes);
        double minValue, maxValue;
        OpenCvSharp.Point location, point;
        OpenCvSharp.Cv2.MinMaxLoc(OpenCvSharp.InputArray.Create(outArray.GetMat()), out minValue, out maxValue, out location, out point);
        Console.WriteLine(maxValue);
        if (maxValue >= threshold)
          return new System.Drawing.Point(point.X, point.Y);
        return System.Drawing.Point.Empty;
      }
      catch(Exception ex)
      {
        return System.Drawing.Point.Empty;
      }
      finally
      {
        if (srcMat != null)
          srcMat.Dispose();
        if (dstMat != null)
          dstMat.Dispose();
        if (outArray != null)
          outArray.Dispose();
      }
    }

C#中OpenCvSharp 通過特征點匹配圖片的方法

總結

以上所述是小編給大家介紹的C#中OpenCvSharp 通過特征點匹配圖片,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對億速云網站的支持!
如果你覺得本文對你有幫助,歡迎轉載,煩請注明出處,謝謝!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女