Files
better-genshin-impact/BetterGenshinImpact/GameTask/AutoPathing/Navigation.cs
Juemin Lin 2b9a4f111a 视角识别算法优化,启用新的视角识别,分层地图小修改,启用模板匹配分层地图 (#1787)
* 小地图预处理和视角识别算法优化

* 模板匹配的相关类,包括快速带遮罩的SqDiff模板匹配,模板匹配归一化类,简易亚像素模板匹配实现,小地图匹配相关配置,和小地图匹配上下文。

* 实现小地图的分层地图模板匹配,修改 SceneBaseMap 的 GetMiniMapPosition 为 virtual 以便继承覆盖。

* 优化视角识别算法, 消除图标对视角识别影响, 修正上次提交里HImg的范围错误(BGR2HLS_FULL模式下H的范围在0~255), 启用新的视角识别算法。

* 模板匹配分层地图小修改

* 启用模板匹配的分层地图
2025-07-01 01:50:27 +08:00

113 lines
3.5 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using BetterGenshinImpact.GameTask.AutoPathing.Model;
using BetterGenshinImpact.GameTask.Model.Area;
using OpenCvSharp;
using System;
using BetterGenshinImpact.GameTask.Common.Element.Assets;
using CommunityToolkit.Mvvm.Messaging;
using CommunityToolkit.Mvvm.Messaging.Messages;
using BetterGenshinImpact.GameTask.Common.Map.Maps;
using BetterGenshinImpact.GameTask.Common.Map.Maps.Base;
namespace BetterGenshinImpact.GameTask.AutoPathing;
public class Navigation
{
private static bool _isWarmUp = false;
private static float _prevX = -1;
private static float _prevY = -1;
public static void WarmUp()
{
if (!_isWarmUp)
{
MapManager.GetMap(MapTypes.Teyvat);
}
_isWarmUp = true;
Reset();
}
public static void Reset()
{
(_prevX, _prevY) = (-1, -1);
}
public static void SetPrevPosition(float x, float y)
{
(_prevX, _prevY) = (x, y);
}
public static Point2f GetPosition(ImageRegion imageRegion, string mapName)
{
var colorMat = new Mat(imageRegion.SrcMat, MapAssets.Instance.MimiMapRect);
var p = MapManager.GetMap(mapName).GetMiniMapPosition(colorMat, _prevX, _prevY);
if (p != default)
{
(_prevX, _prevY) = (p.X, p.Y);
}
WeakReferenceMessenger.Default.Send(new PropertyChangedMessage<object>(typeof(Navigation),
"SendCurrentPosition", new object(), p));
return p;
}
/// <summary>
/// 稳定获取当前位置坐标,优先使用全地图匹配,适用于不需要高效率但需要高稳定性的场景
/// </summary>
/// <param name="imageRegion">图像区域</param>
/// <param name="mapName"></param>
/// <returns>当前位置坐标</returns>
public static Point2f GetPositionStable(ImageRegion imageRegion, string mapName)
{
var colorMat = new Mat(imageRegion.SrcMat, MapAssets.Instance.MimiMapRect);
// 先尝试使用局部匹配
var p = MapManager.GetMap(mapName).GetMiniMapPosition(colorMat, _prevX, _prevY);
// 如果局部匹配失败,再尝试全地图匹配失败
if (p == new Point2f())
{
Reset();
p = MapManager.GetMap(mapName).GetMiniMapPosition(colorMat, _prevX, _prevY);
}
if (p != default)
{
(_prevX, _prevY) = (p.X, p.Y);
}
WeakReferenceMessenger.Default.Send(new PropertyChangedMessage<object>(typeof(Navigation),
"SendCurrentPosition", new object(), p));
return p;
}
public static int GetTargetOrientation(Waypoint waypoint, Point2f position)
{
double deltaX = waypoint.X - position.X;
double deltaY = waypoint.Y - position.Y;
double vectorLength = Math.Sqrt(deltaX * deltaX + deltaY * deltaY);
if (vectorLength == 0)
{
return 0;
}
// 计算向量与x轴之间的夹角逆时针方向
double angle = Math.Acos(deltaX / vectorLength);
// 如果向量在x轴下方角度需要调整
if (deltaY < 0)
{
angle = 2 * Math.PI - angle;
}
return (int)(angle * (180.0 / Math.PI));
}
public static double GetDistance(Waypoint waypoint, Point2f position)
{
var x1 = waypoint.X;
var y1 = waypoint.Y;
var x2 = position.X;
var y2 = position.Y;
return Math.Sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
}
}