C\#에서 OpenCvsharp 가 특징 점 을 통 해 그림 과 일치 하 는 방법

현재 의 모 바 일 게임 은 기본적으로 반복 적 으로 조작 되 고 한 동작 은 오래 기 다 려 야 하 며 끝 난 후에 다른 동작 을 계속 해 야 한다.매우 번 거 로 워 서 자신 이 게임 을 보조 하 는 마음 을 쓰기 시작 했다.
이 보조 자 체 는 어렵 지 않 습 니 다.바로 끊 임 없 는 캡 처 를 통 해 이 캡 처 에서 해당 동작 을 나타 내 는 버튼 이나 트리거 조건 을 나타 내 는 작은 그림 을 찾 는 것 입 니 다.
찾 으 면 이 하위 영역의 왼쪽 상단 좌 표를 가 져 오고 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);
        }
      }
    }

템 플 릿 일치

 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 이 특징 점 을 통 해 그림 과 일치 하 는 것 입 니 다.여러분 께 도움 이 되 기 를 바 랍 니 다.궁금 한 점 이 있 으 시 면 메 시 지 를 남 겨 주세요.편집장 님 께 서 바로 답 해 드 리 겠 습 니 다.여기 서도 저희 사이트 에 대한 여러분 의 지지 에 감 사 드 립 니 다!
만약 당신 이 본문 이 당신 에 게 도움 이 된다 고 생각한다 면,전 재 를 환영 합 니 다.번 거 로 우 시 겠 지만 출처 를 밝 혀 주 십시오.감사합니다!

좋은 웹페이지 즐겨찾기