diff --git a/BetterGenshinImpact.Test/MainWindow.xaml.cs b/BetterGenshinImpact.Test/MainWindow.xaml.cs index f138cf1e..c102f9f4 100644 --- a/BetterGenshinImpact.Test/MainWindow.xaml.cs +++ b/BetterGenshinImpact.Test/MainWindow.xaml.cs @@ -12,8 +12,10 @@ namespace BetterGenshinImpact.Test InitializeComponent(); // new HsvTestWindow().Run(); - MapPuzzle.Put(); + // MapPuzzle.Put(); // OcrTest.TestYap(); + // MatchTemplateTest.Test(); + MatchTest.Test(); } } } diff --git a/BetterGenshinImpact.Test/MapPuzzle.cs b/BetterGenshinImpact.Test/MapPuzzle.cs index f4e45aca..2b3cece1 100644 --- a/BetterGenshinImpact.Test/MapPuzzle.cs +++ b/BetterGenshinImpact.Test/MapPuzzle.cs @@ -104,7 +104,7 @@ public class MapPuzzle int totalHeight = (lenRow + 1) * block; // 创建空白大图 - Mat largeImage = new Mat(totalHeight, totalWidth, MatType.CV_8UC3, new Scalar(255, 255, 255)); + Mat largeImage = new Mat(totalHeight, totalWidth, MatType.CV_8UC3, new Scalar(0, 0, 0)); // 拼接图片 int[,] arr = new int[lenRow + 1, lenCol + 1]; @@ -145,6 +145,8 @@ public class MapPuzzle // 保存大图 Cv2.ImWrite(@"E:\HuiTask\更好的原神\地图匹配\combined_image.png", largeImage); + Cv2.ImWrite(@"E:\HuiTask\更好的原神\地图匹配\combined_image_sd4x.png", largeImage.Resize(new Size(largeImage.Width / 4, largeImage.Height / 4), 0, 0, InterpolationFlags.Cubic)); + Cv2.ImWrite(@"E:\HuiTask\更好的原神\地图匹配\combined_image_small.png", largeImage.Resize(new Size(1400, 1300), 0, 0, InterpolationFlags.Cubic)); // 释放资源 largeImage.Dispose(); diff --git a/BetterGenshinImpact.Test/MatchTemplateTest.cs b/BetterGenshinImpact.Test/MatchTemplateTest.cs new file mode 100644 index 00000000..6dd8c62b --- /dev/null +++ b/BetterGenshinImpact.Test/MatchTemplateTest.cs @@ -0,0 +1,27 @@ +using BetterGenshinImpact.Core.Recognition.OpenCv; +using OpenCvSharp; + +namespace BetterGenshinImpact.Test; + +public class MatchTemplateTest +{ + 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); + + public static void Test() + { + var tar = new Mat(@"E:\HuiTask\更好的原神\地图匹配\比较\叠图\涂黑匹配2.png", ImreadModes.Color); + var sTar = tar.Resize(new Size(240, 135), 0, 0, InterpolationFlags.Cubic); + // sTar = new Mat(sTar, TemplateSizeRoi); + Cv2.ImShow("sTar", sTar); + var src = new Mat(@"E:\HuiTask\更好的原神\地图匹配\combined_image_small.png", ImreadModes.Color); + var src2 = src.Clone(); + var p = MatchTemplateHelper.MatchTemplate(src, sTar, TemplateMatchModes.CCoeffNormed, null, 0.1); + + Cv2.Rectangle(src2, new Rect(p.X, p.Y, sTar.Width, sTar.Height), new Scalar(0, 0, 255)); + + Cv2.ImWrite(@"E:\HuiTask\更好的原神\地图匹配\x1.png", src2); + } +} diff --git a/BetterGenshinImpact.Test/MatchTest.cs b/BetterGenshinImpact.Test/MatchTest.cs new file mode 100644 index 00000000..5ffb8452 --- /dev/null +++ b/BetterGenshinImpact.Test/MatchTest.cs @@ -0,0 +1,343 @@ +using OpenCvSharp; +using OpenCvSharp.Features2D; +using System.Diagnostics; +using System.IO; +using System.Runtime.InteropServices; +using System.Runtime.Serialization; +using System.Runtime.Serialization.Formatters.Binary; +using System.Xml; + +namespace BetterGenshinImpact.Test; + +public class MatchTest +{ + public static void Test() + { + var tar = new Mat(@"E:\HuiTask\更好的原神\地图匹配\比较\小地图\Clip_20240323_185641.png", ImreadModes.Color); + tar = tar.Resize(new Size(tar.Width * 2, tar.Height * 2), 0, 0, InterpolationFlags.Nearest); + var src = new Mat(@"E:\HuiTask\更好的原神\地图匹配\combined_image.png", ImreadModes.Color); + var res = MatchPicBySurf(src, tar); + + Cv2.ImWrite(@"E:\HuiTask\更好的原神\地图匹配\s1.png", res); + } + + public static Mat MatchPicBySift(Mat matSrc, Mat matTo) + { + Stopwatch sw = new Stopwatch(); + sw.Start(); + + Mat matSrcRet = new Mat(); + using Mat matToRet = new Mat(); + KeyPoint[] keyPointsSrc, keyPointsTo; + using (var sift = SIFT.Create()) + { + var kpPath = @"E:\HuiTask\更好的原神\地图匹配\sift.kp"; + var kpMatPath = @"E:\HuiTask\更好的原神\地图匹配\sift.mat"; + if (File.Exists(kpPath) && File.Exists(kpMatPath)) + { + keyPointsSrc = (KeyPoint[])DeserializeObject(File.ReadAllBytes(kpPath)); + GCHandle pinnedArray = GCHandle.Alloc(DeserializeObject(File.ReadAllBytes(kpMatPath)), GCHandleType.Pinned); + IntPtr pointer = pinnedArray.AddrOfPinnedObject(); + matSrcRet = new Mat(166767, 128, MatType.CV_32FC1, pointer); + } + else + { + sift.DetectAndCompute(matSrc, null, out keyPointsSrc, matSrcRet); + byte[] arr = new byte[matSrcRet.Step(0) * matSrcRet.Rows]; // matSrcRet.Total() * matSrcRet.ElemSize() + Marshal.Copy(matSrcRet.Data, arr, 0, arr.Length); + File.WriteAllBytes(kpMatPath, SerializeObject(arr)); + File.WriteAllBytes(kpPath, SerializeObject(keyPointsSrc)); + } + + sw.Stop(); + Debug.WriteLine($"大地图kp耗时:{sw.ElapsedMilliseconds}ms."); + sw.Restart(); + sift.DetectAndCompute(matTo, null, out keyPointsTo, matToRet); + sw.Stop(); + Debug.WriteLine($"模板kp耗时:{sw.ElapsedMilliseconds}ms."); + sw.Restart(); + } + + using (var bfMatcher = new OpenCvSharp.BFMatcher()) + { + var matches = bfMatcher.KnnMatch(matSrcRet, matToRet, k: 2); + + var pointsSrc = new List(); + var pointsDst = new List(); + var goodMatches = new List(); + 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]); + Debug.WriteLine($"{keyPointsSrc[items[0].QueryIdx].Pt.X}, {keyPointsSrc[items[0].QueryIdx].Pt.Y}"); + } + } + + sw.Stop(); + Debug.WriteLine($"bfMatcher耗时:{sw.ElapsedMilliseconds}ms."); + sw.Restart(); + + var outMat = new Mat(); + + // algorithm RANSAC Filter the matched results + var pSrc = pointsSrc.ConvertAll(Point2fToPoint2d); + var pDst = pointsDst.ConvertAll(Point2fToPoint2d); + var outMask = new Mat(); + // If the original matching result is null, Skip the filtering step + if (pSrc.Count > 0 && pDst.Count > 0) + Cv2.FindHomography(pSrc, pDst, HomographyMethods.Ransac, mask: outMask); + + sw.Stop(); + Debug.WriteLine($"FindHomography耗时:{sw.ElapsedMilliseconds}ms."); + sw.Restart(); + // If passed RANSAC After processing, the matching points are more than 10.,Only filters are used. Otherwise, use the original matching point result(When the matching point is too small, it passes through RANSAC After treatment,It is possible to get the result of 0 matching points.). + if (outMask.Rows > 10) + { + byte[] maskBytes = new byte[outMask.Rows * outMask.Cols]; + outMask.GetArray(out 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); + + sw.Stop(); + Debug.WriteLine($"绘图耗时:{sw.ElapsedMilliseconds}ms."); + sw.Restart(); + return outMat; + } + } + + //This method may be missed, you may read a lot of blogs, but none of them wrote + private static Point2d Point2fToPoint2d(Point2f input) + { + Point2d p2 = new Point2d(input.X, input.Y); + return p2; + } + + public static Mat MatchPicBySurf(Mat matSrc, Mat matTo, double threshold = 400) + { + Stopwatch sw = new Stopwatch(); + sw.Start(); + + Mat matSrcRet = new Mat(); + using Mat matToRet = new Mat(); + KeyPoint[] keyPointsSrc, keyPointsTo; + using (var surf = OpenCvSharp.XFeatures2D.SURF.Create(threshold, 4, 3, true, true)) + { + var kpPath = @"E:\HuiTask\更好的原神\地图匹配\surf.kp"; + var kpMatPath = @"E:\HuiTask\更好的原神\地图匹配\surf.mat"; + if (File.Exists(kpPath) && File.Exists(kpMatPath)) + { + keyPointsSrc = (KeyPoint[])DeserializeObject(File.ReadAllBytes(kpPath)); + GCHandle pinnedArray = GCHandle.Alloc(DeserializeObject(File.ReadAllBytes(kpMatPath)), GCHandleType.Pinned); + IntPtr pointer = pinnedArray.AddrOfPinnedObject(); + matSrcRet = new Mat(166767, 128, MatType.CV_32FC1, pointer); + } + else + { + surf.DetectAndCompute(matSrc, null, out keyPointsSrc, matSrcRet); + byte[] arr = new byte[matSrcRet.Step(0) * matSrcRet.Rows]; // matSrcRet.Total() * matSrcRet.ElemSize() + Marshal.Copy(matSrcRet.Data, arr, 0, arr.Length); + File.WriteAllBytes(kpMatPath, SerializeObject(arr)); + File.WriteAllBytes(kpPath, SerializeObject(keyPointsSrc)); + } + sw.Stop(); + Debug.WriteLine($"大地图kp耗时:{sw.ElapsedMilliseconds}ms."); + sw.Restart(); + + surf.DetectAndCompute(matTo, null, out keyPointsTo, matToRet); + sw.Stop(); + Debug.WriteLine($"模板kp耗时:{sw.ElapsedMilliseconds}ms."); + sw.Restart(); + } + + using (var flnMatcher = new OpenCvSharp.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]); + } + } + + sw.Stop(); + Debug.WriteLine($"flnMatcher耗时:{sw.ElapsedMilliseconds}ms."); + sw.Restart(); + + var outMat = new Mat(); + + // algorithm RANSAC Filter the matched results + var pSrc = pointsSrc.ConvertAll(Point2fToPoint2d); + var pDst = pointsDst.ConvertAll(Point2fToPoint2d); + var outMask = new Mat(); + // If the original matching result is null, Skip the filtering step + if (pSrc.Count > 0 && pDst.Count > 0) + Cv2.FindHomography(pSrc, pDst, HomographyMethods.Ransac, mask: outMask); + sw.Stop(); + Debug.WriteLine($"FindHomography耗时:{sw.ElapsedMilliseconds}ms."); + sw.Restart(); + + // If passed RANSAC After processing, the matching points are more than 10.,Only filters are used. Otherwise, use the original matching point result(When the matching point is too small, it passes through RANSAC After treatment,It's possible to get the result of 0 matching points.). + if (outMask.Rows > 10) + { + Debug.WriteLine($"使用了Ransac的结果"); + byte[] maskBytes = new byte[outMask.Rows * outMask.Cols]; + outMask.GetArray(out 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); + + sw.Stop(); + Debug.WriteLine($"绘图耗时:{sw.ElapsedMilliseconds}ms."); + return outMat; + } + } + + /// + /// 序列化 + /// + /// + /// + private static byte[] Serialize(object obj) + { + using var memoryStream = new MemoryStream(); + DataContractSerializer ser = new DataContractSerializer(typeof(object)); + ser.WriteObject(memoryStream, obj); + var data = memoryStream.ToArray(); + return data; + } + + /// + /// 反序列化 + /// + /// + /// + /// + private static T Deserialize(byte[] data) + { + using var memoryStream = new MemoryStream(data); + XmlDictionaryReader reader = XmlDictionaryReader.CreateTextReader(memoryStream, new XmlDictionaryReaderQuotas()); + DataContractSerializer ser = new DataContractSerializer(typeof(T)); + var result = (T)ser.ReadObject(reader, true); + return result; + } + + [Obsolete("Obsolete")] + public static byte[] SerializeObject(object obj) + { + if (obj == null) + return null; + //内存实例 + MemoryStream ms = new MemoryStream(); + //创建序列化的实例 + BinaryFormatter formatter = new BinaryFormatter(); + formatter.Serialize(ms, obj); //序列化对象,写入ms流中 + byte[] bytes = ms.GetBuffer(); + return bytes; + } + + [Obsolete("Obsolete")] + public static object DeserializeObject(byte[] bytes) + { + object obj = null; + if (bytes == null) + return obj; + //利用传来的byte[]创建一个内存流 + MemoryStream ms = new MemoryStream(bytes); + ms.Position = 0; + BinaryFormatter formatter = new BinaryFormatter(); + obj = formatter.Deserialize(ms); //把内存流反序列成对象 + ms.Close(); + return obj; + } + + static bool WriteRawImage(Mat image, string filename) + { + using (FileStream file = new FileStream(filename, FileMode.Create)) + { + if (file == null || !file.CanWrite) + return false; + + BinaryWriter writer = new BinaryWriter(file); + writer.Write(image.Rows); + writer.Write(image.Cols); + int depth = image.Depth(); + int type = image.Type(); + int channels = image.Channels(); + writer.Write(depth); + writer.Write(type); + writer.Write(channels); + int sizeInBytes = (int)image.Step() * image.Rows; + writer.Write(sizeInBytes); + byte[] arr = new byte[sizeInBytes]; + Marshal.Copy(image.Data, arr, 0, arr.Length); + writer.Write(arr, 0, sizeInBytes); + } + return true; + } + + static bool ReadRawImage(out Mat image, string filename) + { + int rows, cols, data, depth, type, channels; + image = null; + + using (FileStream file = new FileStream(filename, FileMode.Open)) + { + if (file == null || !file.CanRead) + return false; + + try + { + BinaryReader reader = new BinaryReader(file); + rows = reader.ReadInt32(); + cols = reader.ReadInt32(); + depth = reader.ReadInt32(); + type = reader.ReadInt32(); + channels = reader.ReadInt32(); + data = reader.ReadInt32(); + image = new OpenCvSharp.Mat(rows, cols, (OpenCvSharp.MatType)type); + // reader.Read(image.Data, 0, data); + } + catch (Exception) + { + return false; + } + } + + return true; + } +} diff --git a/BetterGenshinImpact/Assets/Map/map_sd1024.png b/BetterGenshinImpact/Assets/Map/map_sd1024.png new file mode 100644 index 00000000..66536cea Binary files /dev/null and b/BetterGenshinImpact/Assets/Map/map_sd1024.png differ diff --git a/BetterGenshinImpact/BetterGenshinImpact.csproj b/BetterGenshinImpact/BetterGenshinImpact.csproj index 4f0ad1ba..ec84e86a 100644 --- a/BetterGenshinImpact/BetterGenshinImpact.csproj +++ b/BetterGenshinImpact/BetterGenshinImpact.csproj @@ -27,6 +27,10 @@ + + + + @@ -82,6 +86,9 @@ Code + + Code + @@ -528,4 +535,8 @@ + + + + \ No newline at end of file diff --git a/BetterGenshinImpact/GameTask/AutoDomain/AutoDomainTask.cs b/BetterGenshinImpact/GameTask/AutoDomain/AutoDomainTask.cs index ae3d5fa3..9e4f2cf9 100644 --- a/BetterGenshinImpact/GameTask/AutoDomain/AutoDomainTask.cs +++ b/BetterGenshinImpact/GameTask/AutoDomain/AutoDomainTask.cs @@ -7,7 +7,6 @@ using BetterGenshinImpact.GameTask.AutoFight.Script; using BetterGenshinImpact.GameTask.AutoGeniusInvokation.Exception; using BetterGenshinImpact.GameTask.AutoPick.Assets; using BetterGenshinImpact.GameTask.Common; -using BetterGenshinImpact.GameTask.Common.MiniMap; using BetterGenshinImpact.GameTask.Model.Enum; using BetterGenshinImpact.Helpers; using BetterGenshinImpact.View.Drawable; @@ -22,6 +21,7 @@ using System.Drawing.Imaging; using System.IO; using System.Threading; using System.Threading.Tasks; +using BetterGenshinImpact.GameTask.Common.Map; using static BetterGenshinImpact.GameTask.Common.TaskControl; using static Vanara.PInvoke.User32; diff --git a/BetterGenshinImpact/GameTask/Common/Map/BigMap.cs b/BetterGenshinImpact/GameTask/Common/Map/BigMap.cs new file mode 100644 index 00000000..873d7be2 --- /dev/null +++ b/BetterGenshinImpact/GameTask/Common/Map/BigMap.cs @@ -0,0 +1,42 @@ +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(this, "UpdateBigMapRect", new object(), + new System.Windows.Rect(p.X, p.Y, TemplateSizeRoi.Width, TemplateSizeRoi.Height))); + } +} diff --git a/BetterGenshinImpact/GameTask/Common/MiniMap/CameraOrientation.cs b/BetterGenshinImpact/GameTask/Common/Map/CameraOrientation.cs similarity index 97% rename from BetterGenshinImpact/GameTask/Common/MiniMap/CameraOrientation.cs rename to BetterGenshinImpact/GameTask/Common/Map/CameraOrientation.cs index 92e2bcd9..f66dddd4 100644 --- a/BetterGenshinImpact/GameTask/Common/MiniMap/CameraOrientation.cs +++ b/BetterGenshinImpact/GameTask/Common/Map/CameraOrientation.cs @@ -1,13 +1,13 @@ -using BetterGenshinImpact.View.Drawable; -using OpenCvSharp; -using System; +using System; using System.Collections.Generic; using System.Drawing; using System.Linq; +using BetterGenshinImpact.View.Drawable; +using OpenCvSharp; using Point = OpenCvSharp.Point; using Size = OpenCvSharp.Size; -namespace BetterGenshinImpact.GameTask.Common.MiniMap; +namespace BetterGenshinImpact.GameTask.Common.Map; public class CameraOrientation { @@ -47,7 +47,6 @@ public class CameraOrientation var left2 = left.Zip(right, (x, y) => Math.Max(x - y, 0)).ToArray(); var right2 = right.Zip(left, (x, y) => Math.Max(x - y, 0)).ToArray(); - // 左移后相乘 在附近2°内寻找最大值 var sum = new int[360]; for (var i = -2; i <= 2; i++) @@ -132,4 +131,4 @@ public class CameraOrientation return LeftShift(array, -k); } } -} \ No newline at end of file +} diff --git a/BetterGenshinImpact/GameTask/Common/MiniMap/CharacterOrientation.cs b/BetterGenshinImpact/GameTask/Common/Map/CharacterOrientation.cs similarity index 95% rename from BetterGenshinImpact/GameTask/Common/MiniMap/CharacterOrientation.cs rename to BetterGenshinImpact/GameTask/Common/Map/CharacterOrientation.cs index 9fe22b20..128164cd 100644 --- a/BetterGenshinImpact/GameTask/Common/MiniMap/CharacterOrientation.cs +++ b/BetterGenshinImpact/GameTask/Common/Map/CharacterOrientation.cs @@ -1,12 +1,7 @@ using BetterGenshinImpact.View.Drawable; using OpenCvSharp; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -namespace BetterGenshinImpact.GameTask.Common.MiniMap; +namespace BetterGenshinImpact.GameTask.Common.Map; public class CharacterOrientation { @@ -112,5 +107,4 @@ public class CharacterOrientation var midY = (p1.Y + p2.Y) / 2; return new Point(midX, midY); } - -} \ No newline at end of file +} diff --git a/BetterGenshinImpact/GameTask/Common/Map/MiniMap.cs b/BetterGenshinImpact/GameTask/Common/Map/MiniMap.cs new file mode 100644 index 00000000..c7198ea1 --- /dev/null +++ b/BetterGenshinImpact/GameTask/Common/Map/MiniMap.cs @@ -0,0 +1,5 @@ +namespace BetterGenshinImpact.GameTask.Common.Map; + +public class MiniMap +{ +} diff --git a/BetterGenshinImpact/GameTask/Common/MiniMap/MiniMap.cs b/BetterGenshinImpact/GameTask/Common/MiniMap/MiniMap.cs deleted file mode 100644 index 51df8e5a..00000000 --- a/BetterGenshinImpact/GameTask/Common/MiniMap/MiniMap.cs +++ /dev/null @@ -1,16 +0,0 @@ -using BetterGenshinImpact.View.Drawable; -using OpenCvSharp; -using System; -using System.Collections.Generic; -using System.Drawing; -using System.Linq; -using Point = OpenCvSharp.Point; -using Size = OpenCvSharp.Size; - -namespace BetterGenshinImpact.GameTask.Common.MiniMap; - -public class MiniMap -{ - - -} \ No newline at end of file diff --git a/BetterGenshinImpact/GameTask/MiniMap/Model/MiniMap.cs b/BetterGenshinImpact/GameTask/MiniMap/Model/MiniMap.cs deleted file mode 100644 index 05150780..00000000 --- a/BetterGenshinImpact/GameTask/MiniMap/Model/MiniMap.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace BetterGenshinImpact.GameTask.MiniMap.Model; - -public class MiniMap -{ -} \ No newline at end of file diff --git a/BetterGenshinImpact/GameTask/Placeholder/PlaceholderTrigger.cs b/BetterGenshinImpact/GameTask/Placeholder/PlaceholderTrigger.cs index ed3d7921..3a372646 100644 --- a/BetterGenshinImpact/GameTask/Placeholder/PlaceholderTrigger.cs +++ b/BetterGenshinImpact/GameTask/Placeholder/PlaceholderTrigger.cs @@ -1,18 +1,12 @@ -using BetterGenshinImpact.Core.Config; +using BetterGenshinImpact.GameTask.Common.Map; using BetterGenshinImpact.View.Drawable; -using Compunet.YoloV8; using OpenCvSharp; using System; using System.Collections.Generic; -using System.Diagnostics; using System.Drawing; -using System.Drawing.Imaging; -using System.IO; using System.Linq; -using BetterGenshinImpact.GameTask.Common.MiniMap; using Point = OpenCvSharp.Point; using Size = OpenCvSharp.Size; -using BetterGenshinImpact.Core.Simulator; namespace BetterGenshinImpact.GameTask.Placeholder; @@ -31,7 +25,9 @@ public class TestTrigger : ITaskTrigger //private readonly AutoGeniusInvokationAssets _autoGeniusInvokationAssets; - private readonly YoloV8 _predictor = new(Global.Absolute("Assets\\Model\\Domain\\bgi_tree.onnx")); + // private readonly YoloV8 _predictor = new(Global.Absolute("Assets\\Model\\Domain\\bgi_tree.onnx")); + + private readonly BigMap _bigMap = new(); public TestTrigger() { @@ -49,24 +45,23 @@ public class TestTrigger : ITaskTrigger { // TestArrow(content); // TestCamera(content); - Detect(content); - var angle = CameraOrientation.Compute(content); - Debug.WriteLine(angle); - if (angle < 180) - { - // 左移视角 - Simulation.SendInputEx.Mouse.MoveMouseBy(-angle, 0); - } - else if (angle is > 180 and < 360) - { - // 右移视角 - Simulation.SendInputEx.Mouse.MoveMouseBy(360 - angle, 0); - } - else - { - // 360 度 东方向视角 - } - + // Detect(content); + // var angle = CameraOrientation.Compute(content); + // Debug.WriteLine(angle); + // if (angle < 180) + // { + // // 左移视角 + // Simulation.SendInputEx.Mouse.MoveMouseBy(-angle, 0); + // } + // else if (angle is > 180 and < 360) + // { + // // 右移视角 + // Simulation.SendInputEx.Mouse.MoveMouseBy(360 - angle, 0); + // } + // else + // { + // // 360 度 东方向视角 + // } //var dictionary = GeniusInvokationControl.FindMultiPicFromOneImage2OneByOne(content.CaptureRectArea.SrcGreyMat, _autoGeniusInvokationAssets.RollPhaseDiceMats, 0.7); //if (dictionary.Count > 0) @@ -88,7 +83,6 @@ public class TestTrigger : ITaskTrigger // Debug.WriteLine("找到了" + i + "个"); //} - //var foundRectArea = content.CaptureRectArea.Find(_autoGeniusInvokationAssets.ElementalTuningConfirmButtonRo); //if (!foundRectArea.IsEmpty()) //{ @@ -98,24 +92,26 @@ public class TestTrigger : ITaskTrigger //{ // Debug.WriteLine("没找到"); //} + + _bigMap.GetMapPositionAndDraw(content.CaptureRectArea.SrcMat); } - private void Detect(CaptureContent content) - { - using var memoryStream = new MemoryStream(); - content.CaptureRectArea.SrcBitmap.Save(memoryStream, ImageFormat.Bmp); - memoryStream.Seek(0, SeekOrigin.Begin); - var result = _predictor.Detect(memoryStream); - Debug.WriteLine(result); - var list = new List(); - foreach (var box in result.Boxes) - { - var rect = new System.Windows.Rect(box.Bounds.X, box.Bounds.Y, box.Bounds.Width, box.Bounds.Height); - list.Add(new RectDrawable(rect, _pen)); - } - - VisionContext.Instance().DrawContent.PutOrRemoveRectList("TreeBox", list); - } + // private void Detect(CaptureContent content) + // { + // using var memoryStream = new MemoryStream(); + // content.CaptureRectArea.SrcBitmap.Save(memoryStream, ImageFormat.Bmp); + // memoryStream.Seek(0, SeekOrigin.Begin); + // var result = _predictor.Detect(memoryStream); + // Debug.WriteLine(result); + // var list = new List(); + // foreach (var box in result.Boxes) + // { + // var rect = new System.Windows.Rect(box.Bounds.X, box.Bounds.Y, box.Bounds.Width, box.Bounds.Height); + // list.Add(new RectDrawable(rect, _pen)); + // } + // + // VisionContext.Instance().DrawContent.PutOrRemoveRectList("TreeBox", list); + // } public static void TestArrow(CaptureContent content) { @@ -220,7 +216,6 @@ public class TestTrigger : ITaskTrigger return new Point(midX, midY); } - public void TestCamera(CaptureContent content) { var mat = new Mat(content.CaptureRectArea.SrcGreyMat, new Rect(62, 19, 212, 212)); @@ -252,7 +247,6 @@ public class TestTrigger : ITaskTrigger var left2 = left.Zip(right, (x, y) => Math.Max(x - y, 0)).ToArray(); var right2 = right.Zip(left, (x, y) => Math.Max(x - y, 0)).ToArray(); - // 左移后相乘 在附近2°内寻找最大值 var sum = new int[360]; for (var i = -2; i <= 2; i++) @@ -328,4 +322,4 @@ public class TestTrigger : ITaskTrigger return LeftShift(array, -k); } } -} \ No newline at end of file +} diff --git a/BetterGenshinImpact/Helpers/ResourceHelper.cs b/BetterGenshinImpact/Helpers/ResourceHelper.cs index 0e2cf166..66b82443 100644 --- a/BetterGenshinImpact/Helpers/ResourceHelper.cs +++ b/BetterGenshinImpact/Helpers/ResourceHelper.cs @@ -18,7 +18,7 @@ internal static class ResourceHelper public static byte[] GetBytes(string uriString) { Uri uri = new(uriString); - StreamResourceInfo info = Application.GetResourceStream(uri); + StreamResourceInfo? info = Application.GetResourceStream(uri); using BinaryReader stream = new(info.Stream); return stream.ReadBytes((int)info.Stream.Length); } @@ -26,14 +26,18 @@ internal static class ResourceHelper public static Stream GetStream(string uriString) { Uri uri = new(uriString); - StreamResourceInfo info = Application.GetResourceStream(uri); + StreamResourceInfo? info = Application.GetResourceStream(uri); return info?.Stream!; } public static string GetString(string uriString, Encoding encoding = null!) { Uri uri = new(uriString); - StreamResourceInfo info = Application.GetResourceStream(uri); + StreamResourceInfo? info = Application.GetResourceStream(uri); + if (info == null) + { + throw new FileNotFoundException($"Resource not found: {uriString}"); + } using StreamReader stream = new(info.Stream, encoding ?? Encoding.UTF8); return stream.ReadToEnd(); } diff --git a/BetterGenshinImpact/View/Pages/CommonSettingsPage.xaml b/BetterGenshinImpact/View/Pages/CommonSettingsPage.xaml index 583a6f02..762c3dea 100644 --- a/BetterGenshinImpact/View/Pages/CommonSettingsPage.xaml +++ b/BetterGenshinImpact/View/Pages/CommonSettingsPage.xaml @@ -309,6 +309,31 @@ + + + + + + + + + + + + + + +