mirror of
https://github.com/babalae/better-genshin-impact.git
synced 2026-04-15 21:03:42 +08:00
149 lines
4.4 KiB
C#
149 lines
4.4 KiB
C#
using BetterGenshinImpact.GameTask.Model.Area;
|
|
using OpenCvSharp;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Drawing;
|
|
using System.Linq;
|
|
using Point = OpenCvSharp.Point;
|
|
using Size = OpenCvSharp.Size;
|
|
|
|
|
|
namespace BetterGenshinImpact.GameTask.Common.Map.Camera;
|
|
|
|
public class CameraOrientationFromGia
|
|
{
|
|
|
|
/// <summary>
|
|
/// 计算当前小地图摄像机朝向的角度
|
|
/// </summary>
|
|
/// <param name="mat">小地图灰度图</param>
|
|
/// <returns>角度</returns>
|
|
public static float ComputeMiniMap(Mat mat)
|
|
{
|
|
// 如果不是灰度图,转换成灰度图
|
|
if (mat.Channels() == 3)
|
|
{
|
|
Cv2.CvtColor(mat, mat, ColorConversionCodes.BGR2GRAY);
|
|
}
|
|
|
|
Cv2.GaussianBlur(mat, mat, new Size(3, 3), 0);
|
|
// 极坐标展开
|
|
var centerPoint = new Point2f(mat.Width / 2f, mat.Height / 2f);
|
|
var polarMat = new Mat();
|
|
Cv2.WarpPolar(mat, polarMat, new Size(360, 360), centerPoint, 360d, InterpolationFlags.Linear, WarpPolarMode.Linear);
|
|
// Cv2.ImShow("polarMat", polarMat);
|
|
var polarRoiMat = new Mat(polarMat, new Rect(10, 0, 70, polarMat.Height));
|
|
Cv2.Rotate(polarRoiMat, polarRoiMat, RotateFlags.Rotate90Counterclockwise);
|
|
|
|
var scharrResult = new Mat();
|
|
Cv2.Scharr(polarRoiMat, scharrResult, MatType.CV_32F, 1, 0);
|
|
|
|
// 求波峰
|
|
var left = new int[360];
|
|
var right = new int[360];
|
|
|
|
scharrResult.GetArray<float>(out var array);
|
|
var leftPeaks = FindPeaks(array);
|
|
leftPeaks.ForEach(i => left[i % 360]++);
|
|
|
|
var reversedArray = array.Select(x => -x).ToArray();
|
|
var rightPeaks = FindPeaks(reversedArray);
|
|
rightPeaks.ForEach(i => right[i % 360]++);
|
|
|
|
// 优化
|
|
var left2 = left.Zip(right, (x, y) => Math.Max(x - y, 0)).ToArray();
|
|
var right2 = right.Zip(left, (x, y) => Math.Max(x - y, 0)).ToArray();
|
|
|
|
// 左移后相乘 在附近2°内寻找最大值
|
|
var sum = new int[360];
|
|
for (var i = -2; i <= 2; i++)
|
|
{
|
|
var all = left2.Zip(Shift(right2, -90 + i), (x, y) => x * y * (3 - Math.Abs(i)) / 3).ToArray();
|
|
sum = sum.Zip(all, (x, y) => x + y).ToArray();
|
|
}
|
|
|
|
// 卷积
|
|
var result = new int[360];
|
|
for (var i = -2; i <= 2; i++)
|
|
{
|
|
var all = Shift(sum, i);
|
|
for (var j = 0; j < all.Length; j++)
|
|
{
|
|
all[j] = all[j] * (3 - Math.Abs(i)) / 3;
|
|
}
|
|
|
|
result = result.Zip(all, (x, y) => x + y).ToArray();
|
|
}
|
|
|
|
// 计算结果角度
|
|
var maxIndex = result.ToList().IndexOf(result.Max());
|
|
var angle = maxIndex + 45;
|
|
if (angle > 360)
|
|
{
|
|
angle -= 360;
|
|
}
|
|
|
|
return angle;
|
|
}
|
|
|
|
public static void DrawDirection(ImageRegion region, double angle, string name = "camera", Pen? pen = null)
|
|
{
|
|
// 绘图
|
|
var scale = TaskContext.Instance().SystemInfo.AssetScale;
|
|
const int r = 100;
|
|
var center = new Point(168 * scale, 125 * scale); // 地图中心点 后续建议调整
|
|
var x1 = center.X + r * Math.Cos(angle * Math.PI / 180);
|
|
var y1 = center.Y + r * Math.Sin(angle * Math.PI / 180);
|
|
|
|
// var line = new LineDrawable(center, new Point(x1, y1))
|
|
// {
|
|
// Pen = new Pen(Color.Yellow, 1)
|
|
// };
|
|
// VisionContext.Instance().DrawContent.PutLine("camera", line);
|
|
|
|
pen ??= new Pen(Color.Yellow, 1);
|
|
|
|
region.DrawLine(center.X, center.Y, (int)x1, (int)y1, name, pen);
|
|
}
|
|
|
|
static List<int> FindPeaks(float[] data)
|
|
{
|
|
List<int> peakIndices = [];
|
|
|
|
for (int i = 1; i < data.Length - 1; i++)
|
|
{
|
|
if (data[i] > data[i - 1] && data[i] > data[i + 1])
|
|
{
|
|
peakIndices.Add(i);
|
|
}
|
|
}
|
|
|
|
return peakIndices;
|
|
}
|
|
|
|
public static int[] RightShift(int[] array, int k)
|
|
{
|
|
return array.Skip(array.Length - k)
|
|
.Concat(array.Take(array.Length - k))
|
|
.ToArray();
|
|
}
|
|
|
|
public static int[] LeftShift(int[] array, int k)
|
|
{
|
|
return array.Skip(k)
|
|
.Concat(array.Take(k))
|
|
.ToArray();
|
|
}
|
|
|
|
public static int[] Shift(int[] array, int k)
|
|
{
|
|
if (k > 0)
|
|
{
|
|
return RightShift(array, k);
|
|
}
|
|
else
|
|
{
|
|
return LeftShift(array, -k);
|
|
}
|
|
}
|
|
} |