key point map test & refactor test window

This commit is contained in:
辉鸭蛋 2024-03-30 22:38:10 +08:00
parent 94da864852
commit 992e1ac3eb
13 changed files with 193 additions and 118 deletions

View File

@ -3,7 +3,5 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:BetterGenshinImpact.Test"
StartupUri="MainWindow.xaml">
<Application.Resources>
</Application.Resources>
<Application.Resources />
</Application>

View File

@ -3,27 +3,34 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:BetterGenshinImpact.Test"
xmlns:oxy="http://oxyplot.org/wpf"
mc:Ignorable="d"
Title="MainWindow" Height="800" Width="400">
<Window.DataContext>
<local:MainViewModel/>
</Window.DataContext>
<Grid>
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<oxy:PlotView
Grid.Row="0"
Model="{Binding LeftModel}"/>
<oxy:PlotView
Grid.Row="1"
Model="{Binding RightModel}"/>
<oxy:PlotView
Grid.Row="2"
Model="{Binding AllModel}"/>
</Grid>
Title="MainWindow"
Width="800"
Height="450"
mc:Ignorable="d">
<Canvas>
<Button Canvas.Left="10"
Canvas.Top="10"
Width="100"
Height="23"
Click="ShowCameraRecWindow"
Content="视角识别测试" />
<Button Canvas.Left="10"
Canvas.Top="40"
Width="100"
Height="23"
Click="ShowHsvTestWindow"
Content="Hsv拉条" />
<Button Canvas.Left="10"
Canvas.Top="70"
Width="100"
Height="23"
Click="DoMapPuzzle"
Content="拼接超大地图" />
<Button Canvas.Left="10"
Canvas.Top="100"
Width="100"
Height="23"
Click="DoMatchTest"
Content="特征匹配测试" />
</Canvas>
</Window>

View File

@ -1,20 +1,47 @@
using System.Windows;
using BetterGenshinImpact.Test.Simple;
using BetterGenshinImpact.Test.Simple.AllMap;
using BetterGenshinImpact.Test.View;
namespace BetterGenshinImpact.Test;
/// <summary>
/// Interaction logic for MainWindow.xaml
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
// new HsvTestWindow().Run();
// MapPuzzle.Put();
// OcrTest.TestYap();
// MatchTemplateTest.Test();
MatchTest.Test();
private void ShowCameraRecWindow(object sender, System.Windows.RoutedEventArgs e)
{
new CameraRecWindow().Show();
}
private void ShowHsvTestWindow(object sender, System.Windows.RoutedEventArgs e)
{
new HsvTestWindow().Run();
}
private void DoMapPuzzle(object sender, System.Windows.RoutedEventArgs e)
{
MapPuzzle.Put();
}
private void DoOcrTest(object sender, System.Windows.RoutedEventArgs e)
{
OcrTest.TestYap();
}
private void DoMatchTemplateTest(object sender, System.Windows.RoutedEventArgs e)
{
MatchTemplateTest.Test();
}
private void DoMatchTest(object sender, System.Windows.RoutedEventArgs e)
{
KeyPointMatchTest.Test();
}
}

View File

@ -1,27 +1,30 @@
using OpenCvSharp;
using OpenCvSharp.Features2D;
using System.Diagnostics;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Xml;
using OpenCvSharp;
namespace BetterGenshinImpact.Test;
namespace BetterGenshinImpact.Test.Simple.AllMap;
public class MatchTest
public class KeyPointMatchTest
{
public static void Test()
{
var tar = new Mat(@"E:\HuiTask\更好的原神\地图匹配\比较\小地图\Clip_20240323_152015.png", ImreadModes.Color);
// var trainMat = new Mat(@"E:\HuiTask\更好的原神\地图匹配\比较\叠图\无法匹配2.png", ImreadModes.Color);
var trainMat = new Mat(@"E:\HuiTask\更好的原神\地图匹配\比较\小地图\Clip_20240323_152015.png", ImreadModes.Grayscale);
// tar = tar.Resize(new Size(tar.Width * 2, tar.Height * 2), 0, 0, InterpolationFlags.Nearest);
var src = new Mat(@"E:\HuiTask\更好的原神\地图匹配\combined_image_2048_lim[quick].png", ImreadModes.Color);
var res = MatchPicBySurf(src, tar);
// var queryMat = new Mat(@"E:\HuiTask\更好的原神\地图匹配\combined_image_lim[quick].png", ImreadModes.Color);
var queryMat = new Mat(@"E:\HuiTask\更好的原神\地图匹配\combined_image_2048_lim[quick].png", ImreadModes.Grayscale);
var res = MatchPicBySurf(trainMat, queryMat);
Cv2.ImWrite(@"E:\HuiTask\更好的原神\地图匹配\s1.png", res);
}
public static Mat MatchPicBySift(Mat matSrc, Mat matTo)
/*public static Mat MatchPicBySift(Mat matSrc, Mat matTo)
{
Stopwatch sw = new Stopwatch();
sw.Start();
@ -108,7 +111,7 @@ public class MatchTest
sw.Restart();
return outMat;
}
}
}*/
//This method may be missed, you may read a lot of blogs, but none of them wrote
private static Point2d Point2fToPoint2d(Point2f input)
@ -127,23 +130,7 @@ public class MatchTest
KeyPoint[] keyPointsSrc, keyPointsTo;
using (var surf = OpenCvSharp.XFeatures2D.SURF.Create(threshold, 4, 3, false, true))
{
var kpPath = @"E:\HuiTask\更好的原神\地图匹配\surf3.kp";
var kpMatPath = @"E:\HuiTask\更好的原神\地图匹配\surf3.mat";
if (File.Exists(kpPath) && File.Exists(kpMatPath) && false)
{
keyPointsSrc = (KeyPoint[])DeserializeObject(File.ReadAllBytes(kpPath));
GCHandle pinnedArray = GCHandle.Alloc(DeserializeObject(File.ReadAllBytes(kpMatPath)), GCHandleType.Pinned);
IntPtr pointer = pinnedArray.AddrOfPinnedObject();
matSrcRet = new Mat(334848, 64, MatType.CV_32FC1, pointer);
}
else
{
surf.DetectAndCompute(matSrc, null, out keyPointsSrc, matSrcRet);
byte[] arr = new byte[matSrcRet.Step(0) * matSrcRet.Rows]; // matSrcRet.Total() * matSrcRet.ElemSize()
Marshal.Copy(matSrcRet.Data, arr, 0, arr.Length);
File.WriteAllBytes(kpMatPath, SerializeObject(arr));
File.WriteAllBytes(kpPath, SerializeObject(keyPointsSrc));
}
surf.DetectAndCompute(matSrc, null, out keyPointsSrc, matSrcRet);
sw.Stop();
Debug.WriteLine($"大地图kp耗时{sw.ElapsedMilliseconds}ms.");
sw.Restart();
@ -154,7 +141,7 @@ public class MatchTest
sw.Restart();
}
using (var flnMatcher = new OpenCvSharp.FlannBasedMatcher())
using (var flnMatcher = new FlannBasedMatcher())
{
var matches = flnMatcher.Match(matSrcRet, matToRet);
//Finding the Minimum and Maximum Distance
@ -205,7 +192,34 @@ public class MatchTest
var outMask = new Mat();
// If the original matching result is null, Skip the filtering step
if (pSrc.Count > 0 && pDst.Count > 0)
Cv2.FindHomography(pSrc, pDst, HomographyMethods.Ransac, mask: outMask);
{
var hMat = Cv2.FindHomography(pSrc, pDst, HomographyMethods.Ransac, mask: outMask);
var objCorners = new Point2f[4];
objCorners[0] = new Point2f(0, 0);
objCorners[1] = new Point2f(0, matSrc.Rows);
objCorners[2] = new Point2f(matSrc.Cols, matSrc.Rows);
objCorners[3] = new Point2f(matSrc.Cols, 0);
var sceneCorners = Cv2.PerspectiveTransform(objCorners, hMat);
// for (int i = 0; i < 4; i++)
// {
// /* 作用和perspectiveTransform一样
// double x = obj_corners[i].x;
// double y = obj_corners[i].y;
// double Z = 1. / (H.At<double>(2, 0) * x + H.At<double>(2, 1) * y + H.At<double>(2, 2));
// double X = (H.At<double>(0, 0) * x + H.At<double>(0, 1) * y + H.At<double>(0, 2)) * Z;
// double Y = (H.At<double>(1, 0) * x + H.At<double>(1, 1) * y + H.At<double>(1, 2)) * Z;
// scene_corners[i] = new Point(cv.Round(X) + img_1.Cols, cv.Round(Y));*/
// sceneCorners[i].X += matSrc.Cols;
// }
Cv2.Line(matTo, sceneCorners[0].ToPoint(), sceneCorners[1].ToPoint(), Scalar.Red, 2);
Cv2.Line(matTo, sceneCorners[1].ToPoint(), sceneCorners[2].ToPoint(), Scalar.Red, 2);
Cv2.Line(matTo, sceneCorners[2].ToPoint(), sceneCorners[3].ToPoint(), Scalar.Red, 2);
Cv2.Line(matTo, sceneCorners[3].ToPoint(), sceneCorners[0].ToPoint(), Scalar.Red, 2);
}
sw.Stop();
Debug.WriteLine($"FindHomography耗时{sw.ElapsedMilliseconds}ms.");
sw.Restart();
@ -329,7 +343,7 @@ public class MatchTest
type = reader.ReadInt32();
channels = reader.ReadInt32();
data = reader.ReadInt32();
image = new OpenCvSharp.Mat(rows, cols, (OpenCvSharp.MatType)type);
image = new Mat(rows, cols, (MatType)type);
// reader.Read(image.Data, 0, data);
}
catch (Exception)

View File

@ -1,10 +1,10 @@
using OpenCvSharp;
using System.Diagnostics;
using System.Diagnostics;
using System.IO;
using System.Security.Cryptography;
using System.Text.RegularExpressions;
using OpenCvSharp;
namespace BetterGenshinImpact.Test;
namespace BetterGenshinImpact.Test.Simple.AllMap;
public class MapPuzzle
{
@ -171,9 +171,9 @@ public class MapPuzzle
public ImgInfo(Mat mat, string name, long fileLength, bool locked = false)
{
this.Img = mat;
this.Name = name;
this.FileLength = fileLength;
Img = mat;
Name = name;
FileLength = fileLength;
Locked = locked;
}
}

View File

@ -1,7 +1,7 @@
using BetterGenshinImpact.Core.Recognition.OpenCv;
using OpenCvSharp;
namespace BetterGenshinImpact.Test;
namespace BetterGenshinImpact.Test.Simple.AllMap;
public class MatchTemplateTest
{

View File

@ -1,42 +1,49 @@
using OpenCvSharp;
namespace BetterGenshinImpact.Test;
namespace BetterGenshinImpact.Test.Simple;
internal class HsvTestWindow
{
private const int MaxValueH = 360 / 2;
static readonly int MaxValue = 255;
private static readonly int MaxValue = 255;
//private const string WindowCaptureName = "Video Capture";
private const string _windowDetectionName = "Object Detection";
static int _lowH = 0, _lowS = 0, _lowV = 0;
static int _highH = MaxValueH, _highS = MaxValue, _highV = MaxValue;
static void on_low_H_thresh_trackbar(int pos, IntPtr userdata)
private static int _lowH = 0, _lowS = 0, _lowV = 0;
private static int _highH = MaxValueH, _highS = MaxValue, _highV = MaxValue;
static void on_low_H_thresh_trackbar(int pos, nint userdata)
{
_lowH = Math.Min(_highH - 1, _lowH);
Cv2.SetTrackbarPos("Low H", _windowDetectionName, _lowH);
}
static void on_high_H_thresh_trackbar(int pos, IntPtr userdata)
static void on_high_H_thresh_trackbar(int pos, nint userdata)
{
_highH = Math.Max(_highH, _lowH + 1);
Cv2.SetTrackbarPos("High H", _windowDetectionName, _highH);
}
static void on_low_S_thresh_trackbar(int pos, IntPtr userdata)
static void on_low_S_thresh_trackbar(int pos, nint userdata)
{
_lowS = Math.Min(_highS - 1, _lowS);
Cv2.SetTrackbarPos("Low S", _windowDetectionName, _lowS);
}
static void on_high_S_thresh_trackbar(int pos, IntPtr userdata)
static void on_high_S_thresh_trackbar(int pos, nint userdata)
{
_highS = Math.Max(_highS, _lowS + 1);
Cv2.SetTrackbarPos("High S", _windowDetectionName, _highS);
}
static void on_low_V_thresh_trackbar(int pos, IntPtr userdata)
static void on_low_V_thresh_trackbar(int pos, nint userdata)
{
_lowV = Math.Min(_highV - 1, _lowV);
Cv2.SetTrackbarPos("Low V", _windowDetectionName, _lowV);
}
static void on_high_V_thresh_trackbar(int pos, IntPtr userdata)
static void on_high_V_thresh_trackbar(int pos, nint userdata)
{
_highV = Math.Max(_highV, _lowV + 1);
Cv2.SetTrackbarPos("High V", _windowDetectionName, _highV);
@ -44,7 +51,6 @@ internal class HsvTestWindow
public void Run()
{
//Cv2.NamedWindow(WindowCaptureName);
Cv2.NamedWindow(_windowDetectionName);
Cv2.ResizeWindow(_windowDetectionName, 900, 900);
@ -76,4 +82,4 @@ internal class HsvTestWindow
}
}
}
}
}

View File

@ -1,7 +1,6 @@
using OpenCvSharp;
using SharpCompress;
namespace BetterGenshinImpact.Test;
namespace BetterGenshinImpact.Test.Simple.MiniMap;
public class CameraOrientationTest
{
@ -138,8 +137,6 @@ public class CameraOrientationTest
}
}
public static void Test2()
{
var mat = Cv2.ImRead(@"E:\HuiTask\更好的原神\自动秘境\视角朝向识别\1.png", ImreadModes.Color);
@ -164,4 +161,4 @@ public class CameraOrientationTest
Cv2.Scharr(splitMat[0], andMat, MatType.CV_8UC1, 1, 0);
Cv2.ImShow("Scharr", andMat);
}
}
}

View File

@ -1,13 +1,8 @@
using BetterGenshinImpact.Core.Recognition.OpenCv;
using System.Diagnostics;
using BetterGenshinImpact.Core.Recognition.OpenCv;
using OpenCvSharp;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BetterGenshinImpact.Test;
namespace BetterGenshinImpact.Test.Simple.MiniMap;
public class CharacterOrientationTest
{
@ -20,8 +15,7 @@ public class CharacterOrientationTest
Cv2.ImShow("gray", gray);
}
static double Distance(OpenCvSharp.Point pt1, OpenCvSharp.Point pt2)
static double Distance(Point pt1, Point pt2)
{
int deltaX = Math.Abs(pt2.X - pt1.X);
int deltaY = Math.Abs(pt2.Y - pt1.Y);
@ -69,13 +63,13 @@ public class CharacterOrientationTest
double perimeter = Cv2.ArcLength(contours[i], true);
// 近似多边形拟合
OpenCvSharp.Point[] approx = Cv2.ApproxPolyDP(contours[i], 0.04 * perimeter, true);
Point[] approx = Cv2.ApproxPolyDP(contours[i], 0.04 * perimeter, true);
// 如果拟合的多边形有三个顶点,认为是三角形
if (approx.Length == 3)
{
// 在图像上绘制三角形的轮廓
Cv2.DrawContours(src, new OpenCvSharp.Point[][] { approx }, -1, Scalar.Green, 1);
Cv2.DrawContours(src, new Point[][] { approx }, -1, Scalar.Green, 1);
// 计算三条边的长度
var sideLengths = new double[3];
sideLengths[0] = Distance(approx[1], approx[2]);
@ -90,7 +84,7 @@ public class CharacterOrientationTest
// 计算最短线的中点
var residue = approx.ToList();
residue.RemoveAt(result.Index);
var midPoint = new OpenCvSharp.Point((residue[0].X + residue[1].X) / 2, (residue[0].Y + residue[1].Y) / 2);
var midPoint = new Point((residue[0].X + residue[1].X) / 2, (residue[0].Y + residue[1].Y) / 2);
// 在图像上绘制直线
Cv2.Line(src, midPoint, approx[result.Index] + (approx[result.Index] - midPoint) * 3, Scalar.Red, 1);
@ -102,7 +96,6 @@ public class CharacterOrientationTest
Cv2.ImShow("目标2", src);
}
public static void TestArrow2()
{
var mat = Cv2.ImRead(@"E:\HuiTask\更好的原神\自动秘境\箭头识别\s1.png", ImreadModes.Color);
@ -202,7 +195,6 @@ public class CharacterOrientationTest
return angleDegrees;
}
public static void FloodFill()
{
var mat = Cv2.ImRead(@"E:\HuiTask\更好的原神\自动秘境\箭头识别\s1.png", ImreadModes.Color);
@ -260,7 +252,6 @@ public class CharacterOrientationTest
}
}
public static void Hsv()
{
var mat = Cv2.ImRead(@"E:\HuiTask\更好的原神\自动秘境\箭头识别\e1.png", ImreadModes.Color);
@ -315,11 +306,10 @@ public class CharacterOrientationTest
if (approx.Length == 3)
{
// 在图像上绘制三角形的轮廓
Cv2.DrawContours(mat, new OpenCvSharp.Point[][] { approx }, -1, Scalar.Green, 1);
Cv2.DrawContours(mat, new Point[][] { approx }, -1, Scalar.Green, 1);
// 剪裁出三角形所在区域
var newSrcMat = new Mat(mat, maxRect);
// HSV 阈值取出中心飞镖
var hsvMat = new Mat();
@ -369,4 +359,4 @@ public class CharacterOrientationTest
}
}
}
}
}

View File

@ -1,10 +1,10 @@
using BetterGenshinImpact.Core.Recognition.ONNX.SVTR;
using System.Diagnostics;
using BetterGenshinImpact.Core.Recognition.OCR;
using BetterGenshinImpact.Core.Recognition.ONNX.SVTR;
using BetterGenshinImpact.Core.Recognition.OpenCv;
using OpenCvSharp;
using System.Diagnostics;
using BetterGenshinImpact.Core.Recognition.OCR;
namespace BetterGenshinImpact.Test;
namespace BetterGenshinImpact.Test.Simple;
public class OcrTest
{

View File

@ -1,21 +1,20 @@
using OxyPlot;
using BetterGenshinImpact.Test.Simple.MiniMap;
using OxyPlot;
using OxyPlot.Series;
using OxyPlot.Wpf;
namespace BetterGenshinImpact.Test;
namespace BetterGenshinImpact.Test.View;
internal class MainViewModel
internal class CameraRecViewModel
{
public PlotModel LeftModel { get; private set; }
public PlotModel RightModel { get; private set; }
public PlotModel AllModel { get; private set; }
public MainViewModel()
public CameraRecViewModel()
{
var data = CameraOrientationTest.Test1();
LeftModel = BuildModel(data.Item1,"左");
LeftModel = BuildModel(data.Item1, "左");
RightModel = BuildModel(data.Item2, "右(左移90度后)");
AllModel = BuildModel(data.Item3, "乘积");
}
@ -37,5 +36,4 @@ internal class MainViewModel
plotModel.Title = name;
return plotModel;
}
}
}

View File

@ -0,0 +1,26 @@
<Window x:Class="BetterGenshinImpact.Test.View.CameraRecWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:BetterGenshinImpact.Test"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:oxy="http://oxyplot.org/wpf"
xmlns:view="clr-namespace:BetterGenshinImpact.Test.View"
Title="MainWindow"
Width="400"
Height="800"
mc:Ignorable="d">
<Window.DataContext>
<view:CameraRecViewModel />
</Window.DataContext>
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<oxy:PlotView Grid.Row="0" Model="{Binding LeftModel}" />
<oxy:PlotView Grid.Row="1" Model="{Binding RightModel}" />
<oxy:PlotView Grid.Row="2" Model="{Binding AllModel}" />
</Grid>
</Window>

View File

@ -0,0 +1,12 @@
namespace BetterGenshinImpact.Test.View;
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class CameraRecWindow : System.Windows.Window
{
public CameraRecWindow()
{
InitializeComponent();
}
}