diff --git a/BetterGenshinImpact.Test/Simple/AllMap/KeyPointMatchTest.cs b/BetterGenshinImpact.Test/Simple/AllMap/KeyPointMatchTest.cs
index b0f946c8..05f120e3 100644
--- a/BetterGenshinImpact.Test/Simple/AllMap/KeyPointMatchTest.cs
+++ b/BetterGenshinImpact.Test/Simple/AllMap/KeyPointMatchTest.cs
@@ -125,19 +125,19 @@ public class KeyPointMatchTest
Stopwatch sw = new Stopwatch();
sw.Start();
- Mat matSrcRet = new Mat();
+ using Mat matSrcRet = new Mat();
using Mat matToRet = new Mat();
KeyPoint[] keyPointsSrc, keyPointsTo;
using (var surf = OpenCvSharp.XFeatures2D.SURF.Create(threshold, 4, 3, false, true))
{
surf.DetectAndCompute(matSrc, null, out keyPointsSrc, matSrcRet);
sw.Stop();
- Debug.WriteLine($"大地图kp耗时:{sw.ElapsedMilliseconds}ms.");
+ Debug.WriteLine($"模板kp耗时:{sw.ElapsedMilliseconds}ms.");
sw.Restart();
surf.DetectAndCompute(matTo, null, out keyPointsTo, matToRet);
sw.Stop();
- Debug.WriteLine($"模板kp耗时:{sw.ElapsedMilliseconds}ms.");
+ Debug.WriteLine($"大地图kp耗时:{sw.ElapsedMilliseconds}ms.");
sw.Restart();
}
diff --git a/BetterGenshinImpact/BetterGenshinImpact.csproj b/BetterGenshinImpact/BetterGenshinImpact.csproj
index ec84e86a..37311e0c 100644
--- a/BetterGenshinImpact/BetterGenshinImpact.csproj
+++ b/BetterGenshinImpact/BetterGenshinImpact.csproj
@@ -27,10 +27,6 @@
-
-
-
-
@@ -92,6 +88,27 @@
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
PreserveNewest
@@ -535,8 +552,4 @@
-
-
-
-
\ No newline at end of file
diff --git a/BetterGenshinImpact/Core/Recognition/OpenCv/CommonExtension.cs b/BetterGenshinImpact/Core/Recognition/OpenCv/CommonExtension.cs
index d5ee9b7e..df3d82c8 100644
--- a/BetterGenshinImpact/Core/Recognition/OpenCv/CommonExtension.cs
+++ b/BetterGenshinImpact/Core/Recognition/OpenCv/CommonExtension.cs
@@ -1,5 +1,6 @@
using OpenCvSharp;
using System;
+using System.Collections.Generic;
using System.Drawing;
using Vanara.PInvoke;
using Color = System.Windows.Media.Color;
@@ -76,4 +77,14 @@ public static class CommonExtension
{
return Color.FromArgb(color.A, color.R, color.G, color.B);
}
+
+ public static Point2d ToPoint2d(this Point2f p)
+ {
+ return new Point2d(p.X, p.Y);
+ }
+
+ public static List ToPoint2d(this List list)
+ {
+ return list.ConvertAll(ToPoint2d);
+ }
}
diff --git a/BetterGenshinImpact/Core/Recognition/OpenCv/SurfMatcher.cs b/BetterGenshinImpact/Core/Recognition/OpenCv/SurfMatcher.cs
new file mode 100644
index 00000000..5ba48468
--- /dev/null
+++ b/BetterGenshinImpact/Core/Recognition/OpenCv/SurfMatcher.cs
@@ -0,0 +1,102 @@
+using OpenCvSharp;
+using OpenCvSharp.XFeatures2D;
+using System.Collections.Generic;
+using System;
+using System.Diagnostics;
+using BetterGenshinImpact.Helpers;
+
+namespace BetterGenshinImpact.Core.Recognition.OpenCv;
+
+public class SurfMatcher
+{
+ private readonly double _threshold;
+ private readonly Mat _matToRet = new();
+ private readonly KeyPoint[] _keyPointsTo;
+
+ public SurfMatcher(Mat matTo, double threshold = 400)
+ {
+ _threshold = threshold;
+ using var surf = SURF.Create(_threshold, 4, 3, false, true);
+ surf.DetectAndCompute(matTo, null, out _keyPointsTo, _matToRet);
+ Debug.WriteLine("被匹配的图像生成初始化KeyPoint完成");
+ }
+
+ public Point2f[]? Match(Mat matSrc)
+ {
+ SpeedTimer speedTimer = new();
+
+ using var matSrcRet = new Mat();
+ KeyPoint[] keyPointsSrc;
+ using (var surf = SURF.Create(_threshold, 4, 3, false, true))
+ {
+ surf.DetectAndCompute(matSrc, null, out keyPointsSrc, matSrcRet);
+ speedTimer.Record("模板生成KeyPoint");
+ }
+
+ using var flnMatcher = new FlannBasedMatcher();
+ var matches = flnMatcher.Match(matSrcRet, _matToRet);
+ //Finding the Minimum and Maximum Distance
+ double minDistance = 1000; //Backward approximation
+ 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;
+ }
+ }
+
+ Debug.WriteLine($"max distance : {maxDistance}");
+ Debug.WriteLine($"min distance : {minDistance}");
+
+ var pointsSrc = new List();
+ var pointsDst = new List();
+ //Screening better matching points
+ // var goodMatches = new List();
+ 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);
+ //Compression of new ones with distances less than ranges DMatch
+ // goodMatches.Add(matches[i]);
+ }
+ }
+
+ speedTimer.Record("FlannMatch");
+
+ // var outMat = new Mat();
+
+ // algorithm RANSAC Filter the matched results
+ var pSrc = pointsSrc.ToPoint2d();
+ var pDst = pointsDst.ToPoint2d();
+ var outMask = new Mat();
+ // If the original matching result is null, Skip the filtering step
+ if (pSrc.Count > 0 && pDst.Count > 0)
+ {
+ var hMat = Cv2.FindHomography(pSrc, pDst, HomographyMethods.Ransac, mask: outMask);
+ speedTimer.Record("FindHomography");
+
+ var objCorners = new Point2f[4];
+ objCorners[0] = new Point2f(0, 0);
+ objCorners[1] = new Point2f(0, matSrc.Rows);
+ objCorners[2] = new Point2f(matSrc.Cols, matSrc.Rows);
+ objCorners[3] = new Point2f(matSrc.Cols, 0);
+
+ var sceneCorners = Cv2.PerspectiveTransform(objCorners, hMat);
+ speedTimer.Record("PerspectiveTransform");
+ speedTimer.DebugPrint();
+ return sceneCorners;
+ }
+ speedTimer.DebugPrint();
+ return null;
+ }
+}
diff --git a/BetterGenshinImpact/GameTask/Common/Map/BigMap.cs b/BetterGenshinImpact/GameTask/Common/Map/BigMap.cs
deleted file mode 100644
index 873d7be2..00000000
--- a/BetterGenshinImpact/GameTask/Common/Map/BigMap.cs
+++ /dev/null
@@ -1,42 +0,0 @@
-using System.Diagnostics;
-using BetterGenshinImpact.Core.Recognition.OpenCv;
-using BetterGenshinImpact.Helpers;
-using CommunityToolkit.Mvvm.Messaging;
-using CommunityToolkit.Mvvm.Messaging.Messages;
-using OpenCvSharp;
-using Point = OpenCvSharp.Point;
-using Size = OpenCvSharp.Size;
-
-namespace BetterGenshinImpact.GameTask.Common.Map;
-
-public class BigMap
-{
- public static readonly Size TemplateSize = new(240, 135);
-
- // 对无用部分进行裁剪(左160,上80,下96)
- public static readonly Rect TemplateSizeRoi = new Rect(20, 10, TemplateSize.Width - 20, TemplateSize.Height - 22);
-
- private readonly Mat _mapSrcMat;
-
- public BigMap()
- {
- var stream = ResourceHelper.GetStream(@"pack://application:,,,/Assets/Map/map_sd1024.png");
- _mapSrcMat = Mat.FromStream(stream, ImreadModes.Color);
- }
-
- public Point GetMapPosition(Mat captureMat)
- {
- Cv2.CvtColor(captureMat, captureMat, ColorConversionCodes.BGRA2BGR);
- using var tar = new Mat(captureMat.Resize(TemplateSize, 0, 0, InterpolationFlags.Cubic), TemplateSizeRoi);
- var p = MatchTemplateHelper.MatchTemplate(_mapSrcMat, tar, TemplateMatchModes.CCoeffNormed, null, 0.2);
- Debug.WriteLine($"BigMap Match Template: {p}");
- return p;
- }
-
- public void GetMapPositionAndDraw(Mat captureMat)
- {
- var p = GetMapPosition(captureMat);
- WeakReferenceMessenger.Default.Send(new PropertyChangedMessage