mirror of
https://github.com/babalae/better-genshin-impact.git
synced 2026-05-09 00:34:14 +08:00
init way record
This commit is contained in:
@@ -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;
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
23
BetterGenshinImpact/GameTask/AutoTrackWay/Model/Way.cs
Normal file
23
BetterGenshinImpact/GameTask/AutoTrackWay/Model/Way.cs
Normal 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));
|
||||
}
|
||||
}
|
||||
34
BetterGenshinImpact/GameTask/AutoTrackWay/Model/WayPoint.cs
Normal file
34
BetterGenshinImpact/GameTask/AutoTrackWay/Model/WayPoint.cs
Normal 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
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
45
BetterGenshinImpact/GameTask/Common/Map/MapCoordinate.cs
Normal file
45
BetterGenshinImpact/GameTask/Common/Map/MapCoordinate.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user