diff --git a/BetterGenshinImpact/GameTask/GetGridIcons/GetGridIconsTask.cs b/BetterGenshinImpact/GameTask/GetGridIcons/GetGridIconsTask.cs index c4451cc5..0b0cad57 100644 --- a/BetterGenshinImpact/GameTask/GetGridIcons/GetGridIconsTask.cs +++ b/BetterGenshinImpact/GameTask/GetGridIcons/GetGridIconsTask.cs @@ -14,8 +14,6 @@ using System.Linq; using BetterGenshinImpact.GameTask.Common.Job; using BetterGenshinImpact.Core.Recognition.OCR; using System.IO; -using System.Drawing; -using static Vanara.PInvoke.Gdi32; using OpenCvSharp.Extensions; using BetterGenshinImpact.GameTask.Model.GameUI; @@ -27,8 +25,6 @@ namespace BetterGenshinImpact.GameTask.GetGridIcons; public class GetGridIconsTask : ISoloTask { private readonly ILogger logger = App.GetLogger(); - private readonly InputSimulator input = Simulation.SendInput; - private readonly ReturnMainUiTask _returnMainUiTask = new(); private CancellationToken ct; @@ -38,9 +34,12 @@ public class GetGridIconsTask : ISoloTask private readonly GridScreenName gridScreenName; - public GetGridIconsTask(GridScreenName gridScreenName, int? maxNumToGet = null) + private readonly bool starAsSuffix; + + public GetGridIconsTask(GridScreenName gridScreenName, bool starAsSuffix, int? maxNumToGet = null) { this.gridScreenName = gridScreenName; + this.starAsSuffix = starAsSuffix; this.maxNumToGet = maxNumToGet; IStringLocalizer stringLocalizer = App.GetService>() ?? throw new NullReferenceException(); CultureInfo cultureInfo = new CultureInfo(TaskContext.Instance().Config.OtherConfig.GameCultureInfoName); @@ -60,7 +59,7 @@ public class GetGridIconsTask : ISoloTask Directory.CreateDirectory(directory); GridScreen gridScreen = new GridScreen(gridRoi, gridParams, this.logger, this.ct); - HashSet itemNames = new HashSet(); + HashSet fileNames = new HashSet(); await foreach (ImageRegion itemRegion in gridScreen) { itemRegion.Click(); @@ -70,9 +69,17 @@ public class GetGridIconsTask : ISoloTask using ImageRegion nameRegion = ra1.DeriveCrop(new Rect((int)(ra1.Width * 0.682), (int)(ra1.Width * 0.0625), (int)(ra1.Width * 0.256), (int)(ra1.Width * 0.03125))); var ocrResult = OcrFactory.Paddle.OcrResult(nameRegion.SrcMat); string itemName = ocrResult.Text; - if (itemNames.Add(itemName)) + string itemStar = ""; + if (this.starAsSuffix) { - string filePath = Path.Combine(directory, $"{itemName}.png"); + using ImageRegion starRegion = ra1.DeriveCrop(new Rect((int)(ra1.Width * 0.682), (int)(ra1.Width * 0.1823), (int)(ra1.Width * 0.105), (int)(ra1.Width * 0.02345))); + itemStar = String.Join(string.Empty, Enumerable.Repeat("★", GetStars(starRegion.SrcMat))); + } + + string fileName = itemName + itemStar; + if (fileNames.Add(fileName)) + { + string filePath = Path.Combine(directory, $"{fileName}.png"); Thread saveThread = new Thread(() => { try @@ -81,11 +88,11 @@ public class GetGridIconsTask : ISoloTask { itemRegion.SrcMat.ToBitmap().Save(fs, System.Drawing.Imaging.ImageFormat.Png); } - logger.LogInformation("图片保存成功:{Text}", itemName); + logger.LogInformation("图片保存成功:{Text}", fileName); } catch (Exception e) { - logger.LogError(e, "图片保存失败:{Text}", itemName); + logger.LogError(e, "图片保存失败:{Text}", fileName); } }); saveThread.IsBackground = true; // 设置为后台线程 @@ -93,7 +100,7 @@ public class GetGridIconsTask : ISoloTask } else { - logger.LogInformation("重复的物品:{Text}", itemName); + logger.LogInformation("重复的物品:{Text}", fileName); } count--; @@ -104,4 +111,19 @@ public class GetGridIconsTask : ISoloTask } } } + + /// + /// OCR检测★字符很不稳定,因此用cv + /// 非常简陋的色彩检测,请传入聚焦的图像,勿带入可能的干扰 + /// + /// + /// + public static int GetStars(Mat mat) + { + Scalar yellowLower = new Scalar(50 - 5, 204 - 5, 255 - 5); + Scalar yellowUpper = new Scalar(50 + 5, 204 + 5, 255 + 0); + using Mat mask = mat.InRange(yellowLower, yellowUpper); + var contours = mask.FindContoursAsArray(RetrievalModes.External, ContourApproximationModes.ApproxSimple); + return contours?.Length ?? 0; + } } \ No newline at end of file diff --git a/BetterGenshinImpact/View/Pages/TaskSettingsPage.xaml b/BetterGenshinImpact/View/Pages/TaskSettingsPage.xaml index e5ec95fa..92fd4862 100644 --- a/BetterGenshinImpact/View/Pages/TaskSettingsPage.xaml +++ b/BetterGenshinImpact/View/Pages/TaskSettingsPage.xaml @@ -2329,16 +2329,15 @@ Foreground="{ui:ThemeResource TextFillColorTertiaryBrush}" TextWrapping="Wrap" Grid.ColumnSpan="2"> 须要打开设置-启用保存截图功能,文件保存在 - log/gridIcons - - 以下过长的内容在pr时会搬到教程里去 - - 需要漆黑的背景以降低干扰,比如渊下宫-蛇肠之路的一个锚点,将视角竖直向上看向洞顶 - - 诸如提纳里的耳朵太长了,他装备的物品角标目前无法正确地和正上方的物品图标进行轮廓分割,请手动规避 + + + 点击查看使用教程 + diff --git a/BetterGenshinImpact/ViewModel/Pages/TaskSettingsPageViewModel.cs b/BetterGenshinImpact/ViewModel/Pages/TaskSettingsPageViewModel.cs index 23c9056b..eb63f1c5 100644 --- a/BetterGenshinImpact/ViewModel/Pages/TaskSettingsPageViewModel.cs +++ b/BetterGenshinImpact/ViewModel/Pages/TaskSettingsPageViewModel.cs @@ -538,7 +538,7 @@ public partial class TaskSettingsPageViewModel : ViewModel try { SwitchGetGridIconsEnabled = true; - await new TaskRunner().RunSoloTaskAsync(new GetGridIconsTask(Config.GetGridIconsConfig.GridName, Config.GetGridIconsConfig.MaxNumToGet)); + await new TaskRunner().RunSoloTaskAsync(new GetGridIconsTask(Config.GetGridIconsConfig.GridName, Config.GetGridIconsConfig.StarAsSuffix, Config.GetGridIconsConfig.MaxNumToGet)); } finally { @@ -547,7 +547,7 @@ public partial class TaskSettingsPageViewModel : ViewModel } [RelayCommand] - private void OnGoToGridIconsFolder() + private void OnGoToGetGridIconsFolder() { var path = Global.Absolute(@"log\gridIcons\"); if (!Directory.Exists(path)) @@ -557,6 +557,12 @@ public partial class TaskSettingsPageViewModel : ViewModel Process.Start("explorer.exe", path); } + + [RelayCommand] + private async Task OnGoToGetGridIconsUrlAsync() + { + await Launcher.LaunchUriAsync(new Uri("https://bettergi.com/feats/task/getGridIcons.html")); + } [RelayCommand] private async Task OnSwitchAutoRedeemCode() @@ -596,7 +602,5 @@ public partial class TaskSettingsPageViewModel : ViewModel .RunSoloTaskAsync(new UseRedemptionCodeTask(codes)); SwitchAutoRedeemCodeEnabled = false; } - - } } \ No newline at end of file diff --git a/Test/BetterGenshinImpact.UnitTest/GameTaskTests/GetGridIconsTests/GetGridIconsTaskTest.cs b/Test/BetterGenshinImpact.UnitTest/GameTaskTests/GetGridIconsTests/GetGridIconsTaskTest.cs new file mode 100644 index 00000000..3d632d16 --- /dev/null +++ b/Test/BetterGenshinImpact.UnitTest/GameTaskTests/GetGridIconsTests/GetGridIconsTaskTest.cs @@ -0,0 +1,30 @@ +using BetterGenshinImpact.GameTask.GetGridIcons; +using OpenCvSharp; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BetterGenshinImpact.UnitTest.GameTaskTests.GetGridIconsTests +{ + public class GetGridIconsTaskTest + { + [Theory] + [InlineData(@"AutoArtifactSalvage\ArtifactAffixes.png", 5)] + /// + /// 测试获取物品的黄色星星数,结果应正确 + /// + public void GetStars_ShouldBeRight(string screenshot, int num) + { + // + using Mat mat = new Mat(@$"..\..\..\Assets\{screenshot}"); + + // + int actual = GetGridIconsTask.GetStars(mat); + + // + Assert.Equal(num, actual); + } + } +}