mirror of
https://github.com/babalae/better-genshin-impact.git
synced 2026-04-02 10:45:22 +08:00
* 抽象基础类 * 修改定义 * 抽象出Feature2D相关能力 * 新增地图基类实现 * 临时提交 * 迁移坐标计算 * 加载分层特征数据 * 新增独立地图 层岩巨渊,渊下宫,旧日之海 * 支持不切分特征点匹配 * 添加远古圣山,修改地图参数 * 提瓦特大陆的大地图匹配 * 提瓦特大陆地图大地图位置获取使用256级别的地图 * 替换大地图匹配类 BigMap.cs * 替换小地图匹配类 EntireMap * 修改tp的入参方式,删除无用类 * 兼容新提交的内容 * 修复类方法覆盖不生效的问题 * 修复定位问题,迁移部分 MapCoordinate 的代码。MapCoordinate 标记为废弃 * 更多坐标方法的迁移 * 修复不正确的坐标转换 * 是用正确的特征匹配 * 体积较小的地图动态生成特征 * 路径追踪窗体支持多地图 * 传送时切换独立地图地区 * 更新传送点信息 * 修改独立地图相关命名,使用 Scene(场景) 命名,和原神内部命名保持一致 * 录制支持多独立地图 * 修复地区切换失败的问题
245 lines
8.8 KiB
C#
245 lines
8.8 KiB
C#
using System.Diagnostics;
|
||
using System.IO;
|
||
using System.Security.Cryptography;
|
||
using System.Text.RegularExpressions;
|
||
using OpenCvSharp;
|
||
|
||
namespace BetterGenshinImpact.Test.Simple.AllMap;
|
||
|
||
public class MapPuzzleOther
|
||
{
|
||
public static List<string> PicWhiteHashList = new List<string>
|
||
{
|
||
};
|
||
|
||
public static MD5 Md5Service = MD5.Create();
|
||
|
||
public static void PutAll()
|
||
{
|
||
// 保存1024
|
||
var img1024 = Put(1024);
|
||
Cv2.ImWrite(@"E:\HuiTask\更好的原神\地图匹配\有用的素材\5.2\DeepSea_1024_1x2.png", img1024);
|
||
}
|
||
|
||
public static Mat Put(int block = 1024)
|
||
{
|
||
string folderPath = @"E:\HuiTask\更好的原神\地图匹配\UI_Map_最新"; // 图片文件夹路径
|
||
|
||
// 层岩巨渊 UI_MapBack_TheChasm_
|
||
// 渊下宫 UI_MapBack_AbyssalPalace_
|
||
// UI_MapBack_DeepSea_
|
||
// UI_Map_Volcano_
|
||
string pattern = @"UI_MapBack_DeepSea_([-+]?\d+)_([-+]?\d+)(.*)";
|
||
var images = Directory.GetFiles(folderPath, "*.png", SearchOption.TopDirectoryOnly); // 获取所有图片文件路径
|
||
|
||
// 解析图片位置信息并存储到字典中
|
||
var imageLocations = new Dictionary<(int row, int col), ImgInfo>();
|
||
foreach (var imagePath in images)
|
||
{
|
||
// 远古圣山 特殊逻辑
|
||
// if (imagePath.Contains("UI_Map_Volcano_800_01.png") || imagePath.Contains("UI_Map_Volcano_01.png"))
|
||
// {
|
||
// continue;
|
||
// }
|
||
// if (!imagePath.Contains("UI_Map_Volcano_0_0.png")
|
||
// &&!imagePath.Contains("UI_Map_Volcano_0_-1.png")
|
||
// &&!imagePath.Contains("UI_Map_Volcano_-1_0.png")
|
||
// &&!imagePath.Contains("UI_Map_Volcano_-1_-1.png"))
|
||
// {
|
||
// continue;
|
||
// }
|
||
|
||
// 层岩巨渊 特殊逻辑
|
||
// if (!imagePath.Contains("UI_MapBack_TheChasm_0_0.png")
|
||
// &&!imagePath.Contains("UI_MapBack_TheChasm_0_1.png")
|
||
// &&!imagePath.Contains("UI_MapBack_TheChasm_1_0.png")
|
||
// &&!imagePath.Contains("UI_MapBack_TheChasm_1_1.png"))
|
||
// {
|
||
// continue;
|
||
// }
|
||
|
||
// 旧日之海
|
||
if (!imagePath.Contains("UI_MapBack_DeepSea_1_4.png")
|
||
&&!imagePath.Contains("UI_MapBack_DeepSea_1_3.png"))
|
||
{
|
||
continue;
|
||
}
|
||
|
||
// 获取文件大小
|
||
var fileInfo = new FileInfo(imagePath);
|
||
|
||
// 解析图片名称中的行列信息
|
||
var name = Path.GetFileNameWithoutExtension(imagePath);
|
||
var match = Regex.Match(name, pattern);
|
||
int row, col;
|
||
if (match.Success)
|
||
{
|
||
// Debug.WriteLine($"已匹配 ({match.Groups[1].Value}, {match.Groups[2].Value}) {name}");
|
||
row = int.Parse(match.Groups[1].Value);
|
||
col = int.Parse(match.Groups[2].Value);
|
||
}
|
||
else
|
||
{
|
||
// Debug.WriteLine($"未匹配 {name}");
|
||
continue;
|
||
}
|
||
|
||
// 排除指定行列的图片
|
||
// if ((row, col) == (4, 6) || (row, col) == (5, 6) || (row, col) == (5, 5) || (row, col) == (5, 2) || (row, col) == (5, 1) || (row, col) == (4, 1))
|
||
// {
|
||
// continue;
|
||
// }
|
||
|
||
// 读取图片并计算hash值
|
||
Mat img = Cv2.ImRead(imagePath);
|
||
var hashBytes = Md5Service.ComputeHash(File.ReadAllBytes(imagePath));
|
||
var hash = BitConverter.ToString(hashBytes).Replace("-", "").ToUpperInvariant();
|
||
|
||
if (img.Width < 8)
|
||
{
|
||
Debug.WriteLine($"太小的不要 ({row}, {col}) {img.Width} {img.Height} {name}");
|
||
continue;
|
||
}
|
||
|
||
// 如果当前位置已经有图片了,保留尺寸较大的图片
|
||
if (imageLocations.ContainsKey((row, col)))
|
||
{
|
||
// 如果当前位置的图片已经被hash锁定,跳过
|
||
if (imageLocations[(row, col)].Locked)
|
||
{
|
||
Debug.WriteLine($"已锁定 ({row}, {col}) {name}");
|
||
continue;
|
||
}
|
||
|
||
if (img.Width > imageLocations[(row, col)].Img.Width || fileInfo.Length > imageLocations[(row, col)].FileLength || PicWhiteHashList.Contains(hash))
|
||
{
|
||
imageLocations[(row, col)] = new ImgInfo(img, name, fileInfo.Length, PicWhiteHashList.Contains(hash));
|
||
}
|
||
else
|
||
{
|
||
Debug.WriteLine($"重复 ({row}, {col}) {img.Width} {img.Height} {name}");
|
||
}
|
||
}
|
||
else
|
||
{
|
||
imageLocations[(row, col)] = new ImgInfo(img, name, fileInfo.Length, PicWhiteHashList.Contains(hash));
|
||
}
|
||
}
|
||
|
||
int minRow = imageLocations.Keys.Min(key => key.row);
|
||
int minCol = imageLocations.Keys.Min(key => key.col);
|
||
|
||
// 确定大图的行数和列数
|
||
int maxRow = imageLocations.Keys.Max(key => key.row);
|
||
int maxCol = imageLocations.Keys.Max(key => key.col);
|
||
|
||
// 计算大图的总宽度和高度
|
||
var lenCol = maxCol - minCol;
|
||
var lenRow = maxRow - minRow;
|
||
Debug.WriteLine($"列数X: {lenCol + 1}, 行数Y: {lenRow + 1}");
|
||
int totalWidth = (lenCol + 1) * block;
|
||
int totalHeight = (lenRow + 1) * block;
|
||
|
||
// 创建空白大图
|
||
Mat largeImage = new Mat(totalHeight, totalWidth, MatType.CV_8UC3, new Scalar(0, 0, 0));
|
||
|
||
// 拼接图片
|
||
int[,] arr = new int[lenRow + 1, lenCol + 1];
|
||
foreach (var location in imageLocations)
|
||
{
|
||
int row = location.Key.row - minRow;
|
||
int col = location.Key.col - minCol;
|
||
Mat img = location.Value.Img;
|
||
|
||
arr[row, col] = 1;
|
||
|
||
// 计算当前图片在大图中的左上角位置
|
||
int x = (lenCol - col) * block; // 顺序倒过来了,屮
|
||
int y = (lenRow - row) * block; // 顺序倒过来了,屮
|
||
|
||
// 将图片粘贴到大图上
|
||
if (img.Width != block || img.Height != block)
|
||
{
|
||
img = img.Resize(new Size(block, block), 0, 0, InterpolationFlags.Nearest);
|
||
}
|
||
|
||
// 添加位置标识
|
||
// img.PutText($"{location.Key.row} , {location.Key.col}", new Point(50, 50), HersheyFonts.HersheyComplex, 2, Scalar.Red, 2, LineTypes.Link8);
|
||
|
||
img.CopyTo(new Mat(largeImage, new Rect(x, y, img.Width, img.Height)));
|
||
}
|
||
|
||
// 康康二维数组的拼接结果
|
||
for (int i = 0; i < arr.GetLength(0); i++)
|
||
{
|
||
for (int j = 0; j < arr.GetLength(1); j++)
|
||
{
|
||
Debug.Write(arr[i, j] + " ");
|
||
}
|
||
|
||
Debug.WriteLine("");
|
||
}
|
||
|
||
// 地图图片块
|
||
// SaveImagesAs1024X1024(arr, imageLocations, @"E:\HuiTask\更好的原神\地图匹配\有用的素材\5.0\地图块", minRow, minCol);
|
||
|
||
|
||
// Cv2.ImWrite(@"E:\HuiTask\更好的原神\地图匹配\combined_image_small.png", largeImage.Resize(new Size(1400, 1300), 0, 0, InterpolationFlags.Cubic));
|
||
|
||
// 释放资源
|
||
return largeImage;
|
||
}
|
||
|
||
public static void SaveImagesAs1024X1024(int[,] arr, Dictionary<(int row, int col), ImgInfo> imageLocations, string outputFolder, int minRow, int minCol)
|
||
{
|
||
if (!Directory.Exists(outputFolder))
|
||
{
|
||
Directory.CreateDirectory(outputFolder);
|
||
}
|
||
|
||
for (int row = 0; row < arr.GetLength(0); row++)
|
||
{
|
||
for (int col = 0; col < arr.GetLength(1); col++)
|
||
{
|
||
if (arr[row, col] == 1)
|
||
{
|
||
var key = (row + minRow, col + minCol);
|
||
if (imageLocations.TryGetValue(key, out var imgInfo))
|
||
{
|
||
var img = imgInfo.Img;
|
||
if (img.Width != 1204 || img.Height != 1204)
|
||
{
|
||
img = imgInfo.Img.Resize(new Size(1024, 1024), 0, 0, InterpolationFlags.Nearest);
|
||
}
|
||
|
||
var outputPath = Path.Combine(outputFolder, $"{row}_{col}.png");
|
||
Cv2.ImWrite(outputPath, img);
|
||
img.Dispose();
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
public class ImgInfo
|
||
{
|
||
public Mat Img { get; set; }
|
||
|
||
public string Name { get; set; }
|
||
|
||
/// <summary>
|
||
/// 文件大小
|
||
/// </summary>
|
||
public long FileLength { get; set; }
|
||
|
||
public bool Locked { get; set; }
|
||
|
||
public ImgInfo(Mat mat, string name, long fileLength, bool locked = false)
|
||
{
|
||
Img = mat;
|
||
Name = name;
|
||
FileLength = fileLength;
|
||
Locked = locked;
|
||
}
|
||
}
|
||
} |