init way record

This commit is contained in:
辉鸭蛋
2024-04-21 23:03:40 +08:00
parent f64e2f37c9
commit 116a4c8790
9 changed files with 209 additions and 35 deletions

View File

@@ -1,7 +1,7 @@
using System.Diagnostics;
using BetterGenshinImpact.Core.Recognition.OpenCv;
using BetterGenshinImpact.Core.Recognition.OpenCv.FeatureMatch;
using BetterGenshinImpact.Helpers;
using OpenCvSharp;
using System.Diagnostics;
namespace BetterGenshinImpact.Test.Simple.AllMap;

View File

@@ -5,6 +5,7 @@ using OpenCvSharp.XFeatures2D;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using BetterGenshinImpact.GameTask.Common.Map;
using OpenCvSharp.Features2D;
namespace BetterGenshinImpact.Core.Recognition.OpenCv.FeatureMatch;
@@ -18,8 +19,8 @@ public class FeatureMatcher
private readonly KeyPoint[] _trainKeyPoints;
private readonly KeyPointFeatureBlock[][] _blocks; // 特征块存储
private readonly int _splitRow = 13 * 2; // 特征点拆分行数
private readonly int _splitCol = 14 * 2; // 特征点拆分列数
private readonly int _splitRow = MapCoordinate.GameMapRows * 2; // 特征点拆分行数
private readonly int _splitCol = MapCoordinate.GameMapCols * 2; // 特征点拆分列数
private KeyPointFeatureBlock? _lastMergedBlock; // 上次合并的特征块
public FeatureMatcher(Mat trainMat, Feature2DType type = Feature2DType.SIFT, double threshold = 100)

View File

@@ -0,0 +1,23 @@
using OpenCvSharp;
using System.Collections.Generic;
using System.Diagnostics;
namespace BetterGenshinImpact.GameTask.AutoTrackWay.Model;
public class Way
{
private List<WayPoint> WayPointList { get; set; } = new();
public void AddPoint(Rect matchRect)
{
// 长宽比例大于 1.5 的矩形不加入
var r = matchRect.Width / (double)matchRect.Height;
if (r is > 1.5 or < 0.66)
{
Debug.WriteLine($"长宽比例不符合要求: {r}");
return;
}
WayPointList.Add(WayPoint.BuildFrom(matchRect, WayPointList.Count));
}
}

View File

@@ -0,0 +1,34 @@
using OpenCvSharp;
using System;
using BetterGenshinImpact.Core.Recognition.OpenCv;
using BetterGenshinImpact.GameTask.Common.Map;
namespace BetterGenshinImpact.GameTask.AutoTrackWay.Model;
/// <summary>
/// 路线点
/// 坐标必须游戏内坐标系
/// </summary>
[Serializable]
public class WayPoint
{
public Point Pt { get; set; }
public Rect MatchRect { get; set; }
public int Index { get; set; }
public DateTime Time { get; set; }
public static WayPoint BuildFrom(Rect matchRect, int index)
{
var pt = MapCoordinate.Main1024ToGame(matchRect.GetCenterPoint());
return new WayPoint
{
Pt = pt,
MatchRect = new Rect(pt, matchRect.Size),
Index = index,
Time = DateTime.Now
};
}
}

View File

@@ -0,0 +1,53 @@
using BetterGenshinImpact.Core.Recognition.OpenCv;
using BetterGenshinImpact.GameTask.Common.Element.Assets;
using BetterGenshinImpact.GameTask.Common.Map;
using OpenCvSharp;
using System;
using System.Threading;
using System.Threading.Tasks;
using BetterGenshinImpact.GameTask.AutoTrackWay.Model;
using static BetterGenshinImpact.GameTask.Common.TaskControl;
namespace BetterGenshinImpact.GameTask.AutoTrackWay;
public class WayPointRecorder
{
private readonly Lazy<EntireMap> _bigMap = new();
public void Switch()
{
}
public Task RecordTask(CancellationTokenSource cts)
{
return new Task(() =>
{
Way way = new();
while (!cts.Token.IsCancellationRequested)
{
Sleep(10, cts);
var ra = GetRectAreaFromDispatcher();
// 小地图匹配测试
var tar = ElementAssets.Instance.PaimonMenuRo.TemplateImageGreyMat!;
var p = MatchTemplateHelper.MatchTemplate(ra.SrcGreyMat, tar, TemplateMatchModes.CCoeffNormed, null, 0.9);
if (p.X == 0 || p.Y == 0)
{
Sleep(50, cts);
continue;
}
var rect = _bigMap.Value.GetMapPositionByFeatureMatch(new Mat(ra.SrcGreyMat, new Rect(p.X + 24, p.Y - 15, 210, 210)));
if (rect != Rect.Empty)
{
way.AddPoint(rect);
}
else
{
Sleep(50, cts);
}
}
}, cts.Token);
}
}

View File

@@ -0,0 +1,13 @@
using BetterGenshinImpact.Core.Config;
using BetterGenshinImpact.GameTask.Model;
using OpenCvSharp;
using System;
namespace BetterGenshinImpact.GameTask.Common.Element.Assets;
public class MapAssets : BaseAssets<MapAssets>
{
public Lazy<Mat> MainMap100BlockMat { get; } = new(() => new Mat(Global.Absolute(@"Assets\Map\mainMap100Block.png")));
public Lazy<Mat> MainMap1024BlockMat { get; } = new(() => new Mat(@"E:\HuiTask\更好的原神\地图匹配\有用的素材\mainMap1024Block.png", ImreadModes.Grayscale));
}

View File

@@ -6,8 +6,10 @@ using CommunityToolkit.Mvvm.Messaging.Messages;
using OpenCvSharp;
using System;
using System.Diagnostics;
using BetterGenshinImpact.Model;
using Point = OpenCvSharp.Point;
using Size = OpenCvSharp.Size;
using BetterGenshinImpact.GameTask.Common.Element.Assets;
namespace BetterGenshinImpact.GameTask.Common.Map;
@@ -34,7 +36,7 @@ public class EntireMap
/// </summary>
private readonly Mat _cityMap2048BlockMat;
private readonly FeatureMatcher _surfMatcher;
private readonly FeatureMatcher _featureMatcher;
private int _prevX = -1;
private int _prevY = -1;
@@ -42,10 +44,10 @@ public class EntireMap
public EntireMap()
{
// 大地图模板匹配使用的模板
_mainMap100BlockMat = new Mat(Global.Absolute(@"Assets\Map\mainMap100Block.png"));
_mainMap1024BlockMat = new Mat(@"E:\HuiTask\更好的原神\地图匹配\有用的素材\mainMap1024Block.png", ImreadModes.Grayscale);
_mainMap100BlockMat = MapAssets.Instance.MainMap100BlockMat.Value;
_mainMap1024BlockMat = MapAssets.Instance.MainMap1024BlockMat.Value;
// _cityMap2048BlockMat = new Mat(@"E:\HuiTask\更好的原神\地图匹配\有用的素材\cityMap2048Block.png", ImreadModes.Grayscale);
_surfMatcher = new FeatureMatcher(_mainMap1024BlockMat);
_featureMatcher = new FeatureMatcher(_mainMap1024BlockMat);
}
/// <summary>
@@ -74,29 +76,37 @@ public class EntireMap
/// 基于Surf匹配获取地图位置(1024区块)
/// 支持大地图和小地图
/// </summary>
/// <param name="captureGreyMat">灰度图</param>
/// <param name="greyMat">灰度图</param>
/// <returns></returns>
public Rect GetMapPositionBySurf(Mat captureGreyMat)
public Rect GetMapPositionByFeatureMatch(Mat greyMat)
{
Point2f[]? pArray;
if (_prevX != -1 && _prevY != -1)
try
{
pArray = _surfMatcher.Match(captureGreyMat, _prevX, _prevY);
}
else
{
pArray = _surfMatcher.Match(captureGreyMat);
}
Point2f[]? pArray;
if (_prevX != -1 && _prevY != -1)
{
pArray = _featureMatcher.Match(greyMat, _prevX, _prevY);
}
else
{
pArray = _featureMatcher.Match(greyMat);
}
if (pArray == null || pArray.Length < 4)
if (pArray == null || pArray.Length < 4)
{
throw new InvalidOperationException();
}
var rect = Cv2.BoundingRect(pArray);
_prevX = rect.X + rect.Width / 2;
_prevY = rect.Y + rect.Height / 2;
return rect;
}
catch
{
(_prevX, _prevY) = (-1, -1);
throw new InvalidOperationException();
Debug.WriteLine("Surf Match Failed");
return Rect.Empty;
}
var rect = Cv2.BoundingRect(pArray);
_prevX = rect.X + rect.Width / 2;
_prevY = rect.Y + rect.Height / 2;
return rect;
}
// public static Point GetIntersection(Point2f[] points)
@@ -118,18 +128,13 @@ public class EntireMap
// return new Point((int)x, (int)y);
// }
public void GetMapPositionAndDrawBySurf(Mat captureGreyMat)
public void GetMapPositionAndDrawByFeatureMatch(Mat captureGreyMat)
{
try
var rect = GetMapPositionByFeatureMatch(captureGreyMat);
if (rect != Rect.Empty)
{
var rect = GetMapPositionBySurf(captureGreyMat);
WeakReferenceMessenger.Default.Send(new PropertyChangedMessage<object>(this, "UpdateBigMapRect", new object(),
new System.Windows.Rect(rect.X / 10.24, rect.Y / 10.24, rect.Width / 10.24, rect.Height / 10.24)));
}
catch (Exception)
{
(_prevX, _prevY) = (-1, -1);
Debug.WriteLine("Surf Match Failed");
}
}
}

View File

@@ -0,0 +1,45 @@
using System;
using OpenCvSharp;
namespace BetterGenshinImpact.GameTask.Common.Map;
/// <summary>
/// 地图坐标系转换
/// 1. 原神游戏坐标系 Game
/// 2. BetterGI主地图1024区块坐标系 Main1024
/// </summary>
public class MapCoordinate
{
public static readonly int GameMapRows = 13; // 游戏坐标下地图块的行数
public static readonly int GameMapCols = 14; // 游戏坐标下地图块的列数
public static readonly int GameMapUpRows = 5; // 游戏坐标下 左上角离地图原点的行数
public static readonly int GameMapLeftCols = 7; // 游戏坐标下 左上角离地图原点的列数
public static readonly int GameMapBlockWidth = 1024; // 游戏地图块的长宽
/// <summary>
/// 原神游戏坐标系 -> 主地图1024区块坐标系
/// </summary>
/// <param name="position">[a,b,c]</param>
/// <returns></returns>
public static Point GameToMain1024(decimal[] position)
{
// 四舍六入五取偶
var a = (int)Math.Round(position[0]); // 上
var c = (int)Math.Round(position[2]); // 左
// 转换1024区块坐标大地图坐标系正轴是往左上方向的
// 这里写最左上角的区块坐标(GameMapUpRows,GameMapLeftCols)/(上,左),截止4.5版本,最左上角的区块坐标是(5,7)
return new Point((GameMapLeftCols + 1) * GameMapBlockWidth - c, (GameMapUpRows + 1) * GameMapBlockWidth - a);
}
/// <summary>
/// 主地图1024区块坐标系 -> 原神游戏坐标系
/// </summary>
/// <param name="point"></param>
/// <returns></returns>
public static Point Main1024ToGame(Point point)
{
return new Point((GameMapLeftCols + 1) * GameMapBlockWidth - point.X, (GameMapUpRows + 1) * GameMapBlockWidth - point.Y);
}
}

View File

@@ -40,8 +40,8 @@ public class TestTrigger : ITaskTrigger
public void Init()
{
IsEnabled = true;
IsExclusive = true;
IsEnabled = false;
IsExclusive = false;
}
public void OnCapture(CaptureContent content)
@@ -104,7 +104,7 @@ public class TestTrigger : ITaskTrigger
return;
}
_bigMap.Value.GetMapPositionAndDrawBySurf(new Mat(content.CaptureRectArea.SrcGreyMat, new Rect(p.X + 24, p.Y - 15, 210, 210)));
_bigMap.Value.GetMapPositionAndDrawByFeatureMatch(new Mat(content.CaptureRectArea.SrcGreyMat, new Rect(p.X + 24, p.Y - 15, 210, 210)));
// 大地图测试
// var mat = content.CaptureRectArea.SrcGreyMat;