using BetterGenshinImpact.Core.Recognition;
using BetterGenshinImpact.Core.Recognition.OCR;
using BetterGenshinImpact.GameTask.Model;
using BetterGenshinImpact.GameTask.Model.Area;
using BetterGenshinImpact.Helpers;
using Microsoft.Extensions.Logging;
using OpenCvSharp;
using System;
using BetterGenshinImpact.GameTask.AutoPick;
namespace BetterGenshinImpact.GameTask.AutoDomain.Model;
public class ResinStatus
{
///
/// 原粹树脂(1自回体)
///
public int OriginalResinCount { get; set; } = 0;
///
/// 脆弱树脂(60)
///
public int FragileResinCount { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
///
/// 浓缩树脂(60)
///
public int CondensedResinCount { get; set; } = 0;
///
/// 须臾树脂(60壶内购买)
///
public int TransientResinCount { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
public static ResinStatus RecogniseFromRegion(ImageRegion region, ISystemInfo systemInfo, IOcrService ocrService)
{
var status = new ResinStatus();
// 1. 原粹树脂
var assetScale = systemInfo.AssetScale;
var originalResinTopIconRa = new RecognitionObject
{
Name = "OriginalResinTopIcon",
RecognitionType = RecognitionTypes.TemplateMatch,
TemplateImageMat = GameTaskManager.LoadAssetImage("AutoFight", "original_resin_top_icon.png", systemInfo),
DrawOnWindow = false
}.InitTemplate();
using ImageRegion crop1 = region.DeriveCrop(new Rect((int)(1300 * assetScale), (int)(25 * assetScale), (int)(160 * assetScale), (int)(50 * assetScale))); // 数字位数的不同导致了水平方向上宽泛的区域
//Cv2.ImShow("test", crop1.SrcMat);
//Cv2.WaitKey();
var originalResinRes = crop1.Find(originalResinTopIconRa);
if (originalResinRes.IsEmpty())
{
throw new Exception("未找到原粹树脂图标");
}
var originalResinCountRect = new Rect(crop1.X + originalResinRes.Right + (int)(25 * assetScale), (int)(37 * assetScale), (int)(110 * assetScale)/* 考虑最长的“200/200” */, (int)(24 * assetScale));
using ImageRegion originalResinCountRegion = region.DeriveCrop(originalResinCountRect);
string cnt1 = ocrService.OcrWithoutDetector(originalResinCountRegion.SrcMat);
var match = System.Text.RegularExpressions.Regex.Match(cnt1, @"(\d+)\s*[/17]\s*(2|20|200)");
if (match.Success)
{
var numericPart = match.Groups[1].Value;
status.OriginalResinCount = StringUtils.TryExtractPositiveInt(numericPart, 0);
}
// 2. 浓缩树脂
int startX = crop1.X + originalResinRes.Left - (int)(180 * assetScale); // 从原粹树脂图标位置起算
var condensedResinTopIconRa = new RecognitionObject
{
Name = "CondensedResinTopIcon",
RecognitionType = RecognitionTypes.TemplateMatch,
TemplateImageMat = GameTaskManager.LoadAssetImage("AutoFight", "condensed_resin_top_icon.png", systemInfo),
DrawOnWindow = false
}.InitTemplate();
using ImageRegion crop2 = region.DeriveCrop(new Rect(startX, (int)(25 * assetScale), (int)(90 * assetScale), (int)(50 * assetScale)));
var condensedResinRes = crop2.Find(condensedResinTopIconRa);
if (condensedResinRes.IsExist())
{
// 找出 icon 的位置 + 25 ~ icon 的位置+45 就是浓缩树脂的数字,数字宽20
var condensedResinCountRect = new Rect(crop2.X + condensedResinRes.Right + (int)(20 * assetScale), crop2.Y + condensedResinRes.Y, (int)(30 * assetScale), condensedResinRes.Height);
using ImageRegion countRegion = region.DeriveCrop(condensedResinCountRect);
using Mat threshold = countRegion.CacheGreyMat.Threshold(180, 255, ThresholdTypes.Binary);
using Mat bitwiseNot = new Mat();
Cv2.BitwiseNot(threshold, bitwiseNot);
//Cv2.ImShow("bitwise", bitwise);
//Cv2.WaitKey();
string cnt40 = ocrService.OcrWithoutDetector(bitwiseNot);
status.CondensedResinCount = StringUtils.TryExtractPositiveInt(cnt40, 0);
}
return status;
}
public void Print(ILogger logger)
{
// logger.LogInformation("原粹树脂:{Cnt1},浓缩树脂:{Cnt2},须臾树脂:{Cnt3},脆弱树脂:{Cnt4}",
// OriginalResinCount, CondensedResinCount, FragileResinCount, TransientResinCount);
logger.LogInformation("原粹树脂:{Cnt1},浓缩树脂:{Cnt2}",
OriginalResinCount, CondensedResinCount);
}
}