Files
better-genshin-impact/BetterGenshinImpact/GameTask/GetGridIcons/GetGridIconsTask.cs
2025-08-16 13:51:46 +08:00

147 lines
5.6 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.Core.Recognition.OCR;
using BetterGenshinImpact.Core.Simulator;
using BetterGenshinImpact.GameTask.AutoArtifactSalvage;
using BetterGenshinImpact.GameTask.Common.Job;
using BetterGenshinImpact.GameTask.Model.Area;
using BetterGenshinImpact.GameTask.Model.GameUI;
using BetterGenshinImpact.Helpers.Extensions;
using Fischless.WindowsInput;
using Microsoft.Extensions.Logging;
using OpenCvSharp;
using OpenCvSharp.Extensions;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using static BetterGenshinImpact.GameTask.Common.TaskControl;
namespace BetterGenshinImpact.GameTask.GetGridIcons;
/// <summary>
/// 获取Grid界面的物品图标
/// </summary>
public class GetGridIconsTask : ISoloTask
{
private readonly ILogger logger = App.GetLogger<GetGridIconsTask>();
private readonly InputSimulator input = Simulation.SendInput;
private CancellationToken ct;
public string Name => "获取Grid界面物品图标独立任务";
private readonly int? maxNumToGet;
private readonly GridScreenName gridScreenName;
private readonly bool starAsSuffix;
public GetGridIconsTask(GridScreenName gridScreenName, bool starAsSuffix, int? maxNumToGet = null)
{
this.gridScreenName = gridScreenName;
this.starAsSuffix = starAsSuffix;
this.maxNumToGet = maxNumToGet;
}
public async Task Start(CancellationToken ct)
{
this.ct = ct;
switch (this.gridScreenName)
{
case GridScreenName.Weapons:
case GridScreenName.Artifacts:
case GridScreenName.CharacterDevelopmentItems:
case GridScreenName.Food:
case GridScreenName.Materials:
case GridScreenName.Gadget:
case GridScreenName.Quest:
case GridScreenName.PreciousItems:
case GridScreenName.Furnishings:
await new ReturnMainUiTask().Start(ct);
await AutoArtifactSalvageTask.OpenBag(this.gridScreenName, this.input, this.logger, this.ct);
break;
default:
logger.LogInformation("{name}暂不支持自动打开,请提前手动打开界面", gridScreenName.GetDescription());
break;
}
using var ra0 = CaptureToRectArea();
GridScreenParams gridParams = GridScreenParams.Templates[this.gridScreenName];
Rect gridRoi = gridParams.GetRect(ra0);
int count = this.maxNumToGet ?? int.MaxValue;
string directory = Path.Combine(AppContext.BaseDirectory, "log/gridIcons", DateTime.Now.ToString("yyyyMMddHHmmss"));
Directory.CreateDirectory(directory);
GridScreen gridScreen = new GridScreen(gridRoi, gridParams, this.logger, this.ct);
HashSet<string> fileNames = new HashSet<string>();
await foreach (ImageRegion itemRegion in gridScreen)
{
itemRegion.Click();
await Delay(300, ct);
using var ra1 = CaptureToRectArea();
using ImageRegion nameRegion = ra1.DeriveCrop(new Rect((int)(ra1.Width * 0.682), (int)(ra1.Width * 0.0625), (int)(ra1.Width * 0.256), (int)(ra1.Width * 0.03125)));
var ocrResult = OcrFactory.Paddle.OcrResult(nameRegion.SrcMat);
string itemName = ocrResult.Text;
string itemStar = "";
if (this.starAsSuffix)
{
using ImageRegion starRegion = ra1.DeriveCrop(new Rect((int)(ra1.Width * 0.682), (int)(ra1.Width * 0.1823), (int)(ra1.Width * 0.105), (int)(ra1.Width * 0.02345)));
itemStar = String.Join(string.Empty, Enumerable.Repeat("★", GetStars(starRegion.SrcMat)));
}
string fileName = itemName + itemStar;
if (fileNames.Add(fileName))
{
string filePath = Path.Combine(directory, $"{fileName}.png");
Thread saveThread = new Thread(() =>
{
try
{
using (FileStream fs = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None))
{
itemRegion.SrcMat.ToBitmap().Save(fs, System.Drawing.Imaging.ImageFormat.Png);
}
logger.LogInformation("图片保存成功:{Text}", fileName);
}
catch (Exception e)
{
logger.LogError(e, "图片保存失败:{Text}", fileName);
}
});
saveThread.IsBackground = true; // 设置为后台线程
saveThread.Start();
}
else
{
logger.LogInformation("重复的物品:{Text}", fileName);
}
count--;
if (count <= 0)
{
logger.LogInformation("检查次数已耗尽");
break;
}
}
}
/// <summary>
/// OCR检测★字符很不稳定因此用cv
/// 非常简陋的色彩检测,请传入聚焦的图像,勿带入可能的干扰
/// </summary>
/// <param name="mat"></param>
/// <returns></returns>
public static int GetStars(Mat mat)
{
Scalar yellowLower = new Scalar(50 - 5, 204 - 5, 255 - 5);
Scalar yellowUpper = new Scalar(50 + 5, 204 + 5, 255 + 0);
using Mat mask = mat.InRange(yellowLower, yellowUpper);
var contours = mask.FindContoursAsArray(RetrievalModes.External, ContourApproximationModes.ApproxSimple);
return contours?.Length ?? 0;
}
}