From c78a9418e1affbc922632aca30d50945445cd2df Mon Sep 17 00:00:00 2001
From: FishmanTheMurloc <162452111+FishmanTheMurloc@users.noreply.github.com>
Date: Sun, 14 Sep 2025 20:29:52 +0800
Subject: [PATCH] =?UTF-8?q?6.0=E9=B1=BC=E5=AE=9A=E4=B9=89=E5=92=8C?=
=?UTF-8?q?=E6=B5=8B=E8=AF=95=E7=94=A8=E4=BE=8B=20(#2201)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../BetterGenshinImpact.csproj | 2 +-
.../GameTask/AutoFishing/Behaviours.cs | 60 +++++++++++--------
.../GameTask/AutoFishing/Model/BaitType.cs | 6 +-
.../GameTask/AutoFishing/Model/BigFishType.cs | 7 +++
.../GetGridIcons/GridIconsAccuracyTestTask.cs | 23 ++++---
.../BehavioursTests.ChooseBait.cs | 30 +++++++++-
.../BehavioursTests.ThrowRod.cs | 2 +-
7 files changed, 93 insertions(+), 37 deletions(-)
diff --git a/BetterGenshinImpact/BetterGenshinImpact.csproj b/BetterGenshinImpact/BetterGenshinImpact.csproj
index cb6b5197..8c9883e3 100644
--- a/BetterGenshinImpact/BetterGenshinImpact.csproj
+++ b/BetterGenshinImpact/BetterGenshinImpact.csproj
@@ -43,7 +43,7 @@
-
+
diff --git a/BetterGenshinImpact/GameTask/AutoFishing/Behaviours.cs b/BetterGenshinImpact/GameTask/AutoFishing/Behaviours.cs
index 2aef44cc..3b4696a7 100644
--- a/BetterGenshinImpact/GameTask/AutoFishing/Behaviours.cs
+++ b/BetterGenshinImpact/GameTask/AutoFishing/Behaviours.cs
@@ -150,34 +150,13 @@ namespace BetterGenshinImpact.GameTask.AutoFishing
logger.LogInformation("选择鱼饵 {Text}", blackboard.selectedBait.GetDescription());
// 寻找鱼饵
- using ImageRegion singleRowGrid = imageRegion.DeriveCrop(0.28 * imageRegion.Width, 0.37 * imageRegion.Height, 0.45 * imageRegion.Width, 0.22 * imageRegion.Height);
- using Mat grey = singleRowGrid.SrcMat.CvtColor(ColorConversionCodes.BGR2GRAY);
- using Mat canny = grey.Canny(20, 40);
-
- Cv2.FindContours(canny, out Point[][] contours, out _, RetrievalModes.External, ContourApproximationModes.ApproxSimple, null);
- contours = contours
- .Where(c =>
- {
- Rect r = Cv2.BoundingRect(c);
- if (r.Width < 0.065 * imageRegion.Width * 0.80) // 剔除太小的
- {
- return false;
- }
- if (r.Height == 0)
- {
- return false;
- }
- return Math.Abs((float)r.Width / r.Height - 0.81) < 0.05; // 按形状筛选
- }).ToArray();
- IEnumerable boxes = contours.Select(Cv2.BoundingRect);
-
- foreach (Rect box in boxes)
+ var boxAndBaits = FindBait(imageRegion);
+ ;
+ foreach ((Rect box, string? predName) in boxAndBaits)
{
- using ImageRegion resRa = singleRowGrid.DeriveCrop(box);
- using Mat img125 = resRa.SrcMat.GetGridIcon();
- (string predName, _) = GridIconsAccuracyTestTask.Infer(img125, this.session, this.prototypes);
if (predName == blackboard.selectedBait.GetDescription())
{
+ using ImageRegion resRa = imageRegion.DeriveCrop(box);
resRa.Click();
blackboard.Sleep(700);
// 可能重复点击,所以固定界面点击下
@@ -225,6 +204,37 @@ namespace BetterGenshinImpact.GameTask.AutoFishing
return BehaviourStatus.Running;
}
}
+
+ public IEnumerable<(Rect, string?)> FindBait(ImageRegion imageRegion1080p)
+ {
+ using ImageRegion singleRowGrid = imageRegion1080p.DeriveCrop(0.28 * imageRegion1080p.Width, 0.37 * imageRegion1080p.Height, 0.45 * imageRegion1080p.Width, 0.22 * imageRegion1080p.Height);
+ using Mat grey = singleRowGrid.SrcMat.CvtColor(ColorConversionCodes.BGR2GRAY);
+ using Mat canny = grey.Canny(20, 40);
+
+ Cv2.FindContours(canny, out Point[][] contours, out _, RetrievalModes.External, ContourApproximationModes.ApproxSimple, null);
+ contours = contours
+ .Where(c =>
+ {
+ Rect r = Cv2.BoundingRect(c);
+ if (r.Width < 0.065 * imageRegion1080p.Width * 0.80) // 剔除太小的
+ {
+ return false;
+ }
+ if (r.Height == 0)
+ {
+ return false;
+ }
+ return Math.Abs((float)r.Width / r.Height - 0.81) < 0.05; // 按形状筛选
+ }).ToArray();
+ IEnumerable boxes = contours.Select(Cv2.BoundingRect);
+ foreach (Rect box in boxes)
+ {
+ using ImageRegion resRa = singleRowGrid.DeriveCrop(box);
+ using Mat img125 = resRa.SrcMat.GetGridIcon();
+ (string? predName, _) = GridIconsAccuracyTestTask.Infer(img125, this.session, this.prototypes);
+ yield return (new Rect(singleRowGrid.X + box.X, singleRowGrid.Y + box.Y, box.Width, box.Height), predName);
+ }
+ }
}
[Obsolete]
diff --git a/BetterGenshinImpact/GameTask/AutoFishing/Model/BaitType.cs b/BetterGenshinImpact/GameTask/AutoFishing/Model/BaitType.cs
index 3e269cc8..8f3049d7 100644
--- a/BetterGenshinImpact/GameTask/AutoFishing/Model/BaitType.cs
+++ b/BetterGenshinImpact/GameTask/AutoFishing/Model/BaitType.cs
@@ -21,5 +21,9 @@ public enum BaitType
[Description("澄晶果粒饵")]
SpinelgrainBait,
[Description("温火饵")]
- EmberglowBait
+ EmberglowBait,
+ [Description("槲梭饵")]
+ BerryBait,
+ [Description("清白饵")]
+ RefreshingLakkaBait
}
\ No newline at end of file
diff --git a/BetterGenshinImpact/GameTask/AutoFishing/Model/BigFishType.cs b/BetterGenshinImpact/GameTask/AutoFishing/Model/BigFishType.cs
index 6cf0f561..90162259 100644
--- a/BetterGenshinImpact/GameTask/AutoFishing/Model/BigFishType.cs
+++ b/BetterGenshinImpact/GameTask/AutoFishing/Model/BigFishType.cs
@@ -30,7 +30,11 @@ public class BigFishType
public static readonly BigFishType Rapidfish = new("rapidfish", BaitType.SpinelgrainBait, "斗士急流鱼", 9);
public static readonly BigFishType PhonyUnihornfish = new("phony unihornfish", BaitType.EmberglowBait, "燃素独角鱼", 10);
public static readonly BigFishType MagmaRapidfish = new("magma rapidfish", BaitType.EmberglowBait, "炽岩斗士急流鱼", 9);
+ public static readonly BigFishType SecretSourceScoutSweeper = new ("secret source scout sweeper", BaitType.EmberglowBait, "秘源机关・巡戒使", 9);
+ public static readonly BigFishType MaulerShark = new ("mauler shark", BaitType.RefreshingLakkaBait, "凶凶鲨", 9);
+ public static readonly BigFishType CrystalEye = new("crystal eye", BaitType.RefreshingLakkaBait, "明眼鱼", 9);
+ public static readonly BigFishType AxeheadFish = new ("axehead fish", BaitType.BerryBait, "巨斧鱼", 9);
public static IEnumerable Values
{
@@ -55,6 +59,9 @@ public class BigFishType
yield return Rapidfish;
yield return PhonyUnihornfish;
yield return MagmaRapidfish;
+ yield return MaulerShark;
+ yield return CrystalEye;
+ yield return AxeheadFish;
}
}
diff --git a/BetterGenshinImpact/GameTask/GetGridIcons/GridIconsAccuracyTestTask.cs b/BetterGenshinImpact/GameTask/GetGridIcons/GridIconsAccuracyTestTask.cs
index f34900b5..4e5a9e22 100644
--- a/BetterGenshinImpact/GameTask/GetGridIcons/GridIconsAccuracyTestTask.cs
+++ b/BetterGenshinImpact/GameTask/GetGridIcons/GridIconsAccuracyTestTask.cs
@@ -114,15 +114,15 @@ public class GridIconsAccuracyTestTask : ISoloTask
Task task1 = Delay(300, ct);
// 用模型推理得到的结果
- Task<(string, int)> task2 = Task.Run(() =>
+ Task<(string?, int)> task2 = Task.Run(() =>
{
using Mat icon = itemRegion.SrcMat.GetGridIcon();
return Infer(icon, session, prototypes);
}, ct);
await Task.WhenAll(task1, task2);
- (string, int) result = task2.Result;
- string predName = result.Item1;
+ (string?, int) result = task2.Result;
+ string? predName = result.Item1;
int predStarNum = result.Item2;
// 用CV方法得到的结果
@@ -136,7 +136,11 @@ public class GridIconsAccuracyTestTask : ISoloTask
// 统计结果
total_count++;
- if (itemName.Contains(predName) && predStarNum == itemStarNum)
+ if (predName == null)
+ {
+ logger.LogInformation($"模型没有识别,应为:{itemName}|{itemStarNum}星,❌,正确率{total_acc / total_count:0.00}");
+ }
+ else if (itemName.Contains(predName) && predStarNum == itemStarNum)
{
total_acc++;
logger.LogInformation($"{predName}|{predStarNum}星,✔,正确率{total_acc / total_count:0.00}");
@@ -163,7 +167,7 @@ public class GridIconsAccuracyTestTask : ISoloTask
///
/// (预测名称, 预测星级)
///
- public static (string, int) Infer(Mat mat, InferenceSession session, Dictionary prototypes)
+ public static (string?, int) Infer(Mat mat, InferenceSession session, Dictionary prototypes)
{
if (mat.Size().Width != 125 || mat.Size().Height != 125)
{
@@ -194,15 +198,18 @@ public class GridIconsAccuracyTestTask : ISoloTask
}
if (min2 == null || distance2 < min2)
{
- pred_name = prototype.Key;
min2 = distance2;
+ if (min2 < 10 * 10) // todo:负样本距离10直接读取模型
+ {
+ pred_name = prototype.Key;
+ }
}
}
- if (pred_name == null || min2 == null)
+ if (min2 == null)
{
throw new Exception("特征数据为空");
}
- min2 = Math.Sqrt(min2.Value);
+ // min2 = Math.Sqrt(min2.Value);
int pred_star = results[2].AsEnumerable().ToList().IndexOf(results[2].AsEnumerable().Max());
return (pred_name, pred_star);
}
diff --git a/Test/BetterGenshinImpact.UnitTest/GameTaskTests/AutoFishingTests/BehavioursTests.ChooseBait.cs b/Test/BetterGenshinImpact.UnitTest/GameTaskTests/AutoFishingTests/BehavioursTests.ChooseBait.cs
index d5cfa27d..42c99678 100644
--- a/Test/BetterGenshinImpact.UnitTest/GameTaskTests/AutoFishingTests/BehavioursTests.ChooseBait.cs
+++ b/Test/BetterGenshinImpact.UnitTest/GameTaskTests/AutoFishingTests/BehavioursTests.ChooseBait.cs
@@ -3,6 +3,7 @@ using BetterGenshinImpact.GameTask.AutoFishing;
using BetterGenshinImpact.GameTask.AutoFishing.Model;
using BetterGenshinImpact.GameTask.Model.Area;
using BetterGenshinImpact.GameTask.Model.Area.Converter;
+using BetterGenshinImpact.Helpers.Extensions;
using Microsoft.Extensions.Time.Testing;
using OpenCvSharp;
using System;
@@ -15,10 +16,36 @@ namespace BetterGenshinImpact.UnitTest.GameTaskTests.AutoFishingTests
{
public partial class BehavioursTests
{
+ [Fact]
+ ///
+ /// 测试识别数量不足的鱼饵,由于图标变灰,识别应失败
+ ///
+ public void FindBaitTest_RecognitionShouldFail()
+ {
+ //
+ Mat mat = new Mat(@$"..\..\..\Assets\AutoFishing\202509141339218213_ChooseBait.png");
+ var imageRegion = new ImageRegion(mat, 0, 0, new DesktopRegion(new FakeMouseSimulator()), converter: new ScaleConverter(1d));
+
+ FakeSystemInfo systemInfo = new FakeSystemInfo(new Vanara.PInvoke.RECT(0, 0, mat.Width, mat.Height), 1);
+ var blackboard = new Blackboard();
+
+ //
+ ChooseBait sut = new ChooseBait("-", blackboard, new FakeLogger(), false, systemInfo, new FakeInputSimulator(), this.session, this.prototypes);
+ var result = sut.FindBait(imageRegion).OrderBy(r => r.Item1.X).ToArray();
+
+ //
+ Assert.Equal(3, result.Length);
+ Assert.Equal(BaitType.FruitPasteBait.GetDescription(), result[0].Item2);
+ Assert.Equal(BaitType.BerryBait.GetDescription(), result[1].Item2);
+ Assert.Null(result[2].Item2);
+ }
+
[Theory]
[InlineData(@"20250225101300361_ChooseBait_Succeeded.png", new string[] { "medaka", "butterflyfish", "butterflyfish", "pufferfish" })]
- [InlineData(@"20250226161354285_ChooseBait_Succeeded.png", new string[] { "medaka", "medaka" })] // todo 更新用例
+ [InlineData(@"20250226161354285_ChooseBait_Succeeded.png", new string[] { "medaka" })] // 不稳定的测试用例,因未学习被照亮的场景
[InlineData(@"202503160917566615@900p.png", new string[] { "pufferfish" })]
+ [InlineData(@"202509141339218213_ChooseBait.png", new string[] { "axehead fish" })]
+ [InlineData(@"202509141339218213_ChooseBait.png", new string[] { "mauler shark", "crystal eye", "medaka", "medaka", "medaka" })]
///
/// 测试各种选取鱼饵,结果为成功
///
@@ -50,6 +77,7 @@ namespace BetterGenshinImpact.UnitTest.GameTaskTests.AutoFishingTests
[Theory]
[InlineData(@"20250226161354285_ChooseBait_Succeeded.png", new string[] { "koi" })]
+ [InlineData(@"202509141339218213_ChooseBait.png", new string[] { "mauler shark", "crystal eye" })]
///
/// 测试各种选取鱼饵,结果为失败
///
diff --git a/Test/BetterGenshinImpact.UnitTest/GameTaskTests/AutoFishingTests/BehavioursTests.ThrowRod.cs b/Test/BetterGenshinImpact.UnitTest/GameTaskTests/AutoFishingTests/BehavioursTests.ThrowRod.cs
index 5c0bc914..3c0dd8d8 100644
--- a/Test/BetterGenshinImpact.UnitTest/GameTaskTests/AutoFishingTests/BehavioursTests.ThrowRod.cs
+++ b/Test/BetterGenshinImpact.UnitTest/GameTaskTests/AutoFishingTests/BehavioursTests.ThrowRod.cs
@@ -14,7 +14,6 @@ namespace BetterGenshinImpact.UnitTest.GameTaskTests.AutoFishingTests
{
[Theory]
[InlineData(@"20250225101304534_ThrowRod_Succeeded.png", BaitType.FalseWormBait)]
- [InlineData(@"20250226162217468_ThrowRod_Succeeded.png", BaitType.FruitPasteBait)]
///
/// 测试各种抛竿,结果为成功
///
@@ -43,6 +42,7 @@ namespace BetterGenshinImpact.UnitTest.GameTaskTests.AutoFishingTests
[Theory]
[InlineData(@"20250225101304534_ThrowRod_Succeeded.png", BaitType.RedrotBait)]
[InlineData(@"20250225101304534_ThrowRod_Succeeded.png", BaitType.FakeFlyBait)]
+ [InlineData(@"20250226162217468_ThrowRod_Succeeded.png", BaitType.FruitPasteBait)]
///
/// 测试各种抛竿,未满足HutaoFisher判定,结果为运行中
///