fix auto genius invokation

This commit is contained in:
huiyadanli
2023-11-13 01:27:38 +08:00
parent 117fc39dd2
commit 1356f5208c
4 changed files with 65 additions and 38 deletions

View File

@@ -18,7 +18,7 @@ public partial class AutoGeniusInvokationConfig : ObservableObject
[ObservableProperty] private int _sleepDelay = 0;
public List<Rect> DefaultCharacterCardRects { get; set; } = new List<Rect>()
public List<Rect> DefaultCharacterCardRects { get;} = new List<Rect>()
{
new(667, 632, 165, 282),
new(877, 632, 165, 282),
@@ -29,26 +29,25 @@ public partial class AutoGeniusInvokationConfig : ObservableObject
/// <summary>
/// 骰子数量文字识别区域
/// </summary>
public Rect MyDiceCountRect { get; set; } = new(58, 632, 45, 47); // 42,47
public Rect MyDiceCountRect { get; } = new(58, 632, 45, 47); // 42,47
/// <summary>
/// 角色卡牌区域向左扩展距离包含HP区域
/// </summary>
public int CharacterCardLeftExtend { get; set; } = 20;
public int CharacterCardLeftExtend { get; } = 20;
/// <summary>
/// 角色卡牌区域向右扩展距离,包含充能区域
/// </summary>
public int CharacterCardRightExtend { get; set; } = 14;
public int CharacterCardRightExtend { get; } = 14;
/// <summary>
/// 出战角色卡牌区域向上或者向下的距离差
/// </summary>
public int ActiveCharacterCardSpace { get; set; } = 41;
public int ActiveCharacterCardSpace { get; } = 41;
/// <summary>
/// HP区域 在 角色卡牌区域 的相对位置
/// </summary>
public Rect CharacterCardExtendHpRect { get; set; } = new(-20, 0, 60, 55);
public Rect CharacterCardExtendHpRect { get; } = new(-20, 0, 60, 55);
}

View File

@@ -511,8 +511,8 @@ public class GeniusInvokationControl
// 鼠标移动到中心
ClickGameWindowCenter();
_logger.LogInformation("等待10s对方重投");
Sleep(10000);
_logger.LogInformation("等待5s对方重投");
Sleep(5000);
}
public Point MakeOffset(Point p)
@@ -995,12 +995,10 @@ public class GeniusInvokationControl
Sleep(2000); // 切人动画
}
public void AppendCharacterStatus(Character character, Mat srcMat, int hp = -1)
public void AppendCharacterStatus(Character character, Mat greyMat, int hp = -2)
{
using var gray = new Mat();
Cv2.CvtColor(srcMat, gray, ColorConversionCodes.BGR2GRAY);
// 截取出战角色区域扩展
using var characterMat = new Mat(gray, new Rect(character.Area.X,
using var characterMat = new Mat(greyMat, new Rect(character.Area.X,
character.Area.Y,
character.Area.Width + 40,
character.Area.Height + 10));
@@ -1029,7 +1027,6 @@ public class GeniusInvokationControl
public Character WhichCharacterActiveWithRetry(Duel duel)
{
// 检查角色是否被击败 // 这里又检查一次是因为最后一个角色存活的情况下,会自动出战
// TODO 这个击败识别有问题,需要优化
var defeatedArray = WhatCharacterDefeated(duel.CharacterCardRects);
for (var i = defeatedArray.Length - 1; i >= 0; i--)
{
@@ -1084,7 +1081,9 @@ public class GeniusInvokationControl
{
// 首个相交矩形就是出战角色
duel.CurrentCharacter = duel.Characters[i + 1];
AppendCharacterStatus(duel.CurrentCharacter, srcMat);
var grayMat = new Mat();
Cv2.CvtColor(srcMat, grayMat, ColorConversionCodes.BGR2GRAY);
AppendCharacterStatus(duel.CurrentCharacter, grayMat);
Cv2.Rectangle(srcMat, rect1, Scalar.Yellow);
Cv2.Rectangle(srcMat, duel.CharacterCardRects[i], Scalar.Blue, 2);
@@ -1119,27 +1118,47 @@ public class GeniusInvokationControl
var hpArray = new int[3]; // 1 代表未出战 2 代表出战
for (var i = 0; i < duel.CharacterCardRects.Count; i++)
{
if (duel.Characters[i + 1].IsDefeated)
{
// 已经被击败的角色肯定未出战
hpArray[i] = 1;
continue;
}
var cardRect = duel.CharacterCardRects[i];
// 未出战角色的hp区域
var hpMat = new Mat(srcMat, new Rect(cardRect.X + _config.CharacterCardExtendHpRect.X,
cardRect.Y + _config.CharacterCardExtendHpRect.Y,
_config.CharacterCardExtendHpRect.Width, _config.CharacterCardExtendHpRect.Height));
var text = OcrFactory.Paddle.Ocr(hpMat);
if (string.IsNullOrWhiteSpace(text))
Cv2.ImWrite($"log\\hp_n_{i}.jpg", hpMat);
Debug.WriteLine($"角色{i}未出战HP位置识别结果{text}");
if (!string.IsNullOrWhiteSpace(text))
{
// 说明这个角色未出战
hpArray[i] = 1;
}
hpMat = new Mat(srcMat, new Rect(cardRect.X + _config.CharacterCardExtendHpRect.X,
cardRect.Y + _config.CharacterCardExtendHpRect.Y - _config.ActiveCharacterCardSpace,
_config.CharacterCardExtendHpRect.Width, _config.CharacterCardExtendHpRect.Height));
text = OcrFactory.Paddle.Ocr(hpMat);
if (string.IsNullOrWhiteSpace(text))
else
{
hpArray[i] = 2;
duel.CurrentCharacter = duel.Characters[i + 1];
AppendCharacterStatus(duel.CurrentCharacter, srcMat);
return duel.CurrentCharacter;
hpMat = new Mat(srcMat, new Rect(cardRect.X + _config.CharacterCardExtendHpRect.X,
cardRect.Y + _config.CharacterCardExtendHpRect.Y - _config.ActiveCharacterCardSpace,
_config.CharacterCardExtendHpRect.Width, _config.CharacterCardExtendHpRect.Height));
text = OcrFactory.Paddle.Ocr(hpMat);
Cv2.ImWrite($"log\\hp_active_{i}.jpg", hpMat);
Debug.WriteLine($"角色{i}出战HP位置识别结果{text}");
if (!string.IsNullOrWhiteSpace(text))
{
var hp = -2;
if (Regex.IsMatch(text, @"^[0-9]+$"))
{
hp = int.Parse(text);
}
hpArray[i] = 2;
duel.CurrentCharacter = duel.Characters[i + 1];
AppendCharacterStatus(duel.CurrentCharacter, srcMat, hp);
return duel.CurrentCharacter;
}
}
}
@@ -1147,7 +1166,8 @@ public class GeniusInvokationControl
{
// 找到并不等1的
var index = hpArray.ToList().FindIndex(x => x != 1);
duel.CurrentCharacter = duel.Characters[index];
Debug.WriteLine($"通过OCR HP的方式没有识别到出战角色但是通过排除法确认角色{index + 1}处于出战状态!");
duel.CurrentCharacter = duel.Characters[index + 1];
AppendCharacterStatus(duel.CurrentCharacter, srcMat);
return duel.CurrentCharacter;
}
@@ -1181,15 +1201,17 @@ public class GeniusInvokationControl
/// <summary>
/// 通过OCR识别当前骰子数量
/// </summary>
/// <param name="duel"></param>
/// <returns></returns>
public int GetDiceCountByOcr()
{
var srcMat = CaptureGameGreyMat();
var diceCountMap = new Mat(srcMat, _config.MyDiceCountRect);
var text = OcrFactory.Paddle.Ocr(diceCountMap);
text = text.Replace(" ", "");
_logger.LogInformation("通过OCR识别当前骰子数量: {Text}", text);
if (string.IsNullOrWhiteSpace(text))
{
Cv2.ImWrite("log\\dice_count_empty.jpg", diceCountMap);
return -10;
}
else if (Regex.IsMatch(text, @"^[0-9]+$"))
@@ -1198,6 +1220,7 @@ public class GeniusInvokationControl
}
else
{
Cv2.ImWrite("log\\dice_count_error.jpg", diceCountMap);
return -10;
}
}

View File

@@ -64,7 +64,7 @@ namespace BetterGenshinImpact.GameTask.AutoGeniusInvokation.Model
sb.Append($"角色{Index}");
if (Hp != -2)
{
sb.Append($"Hp={Hp}");
sb.Append($"HP={Hp}");
}
sb.Append($"充能={EnergyByRecognition}");
if (StatusList?.Count > 0)

View File

@@ -5,6 +5,7 @@ using Microsoft.Extensions.Logging;
using OpenCvSharp;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
@@ -145,17 +146,20 @@ public class Duel
// 行动前重新确认骰子数量
var diceCountFromOcr = GeniusInvokationControl.GetInstance().GetDiceCountByOcr();
var diceDiff = Math.Abs(CurrentDiceCount - diceCountFromOcr);
if (diceDiff is > 0 and <= 2)
if (diceCountFromOcr != -10)
{
_logger.LogInformation("可能存在场地牌影响了骰子数[{CurrentDiceCount}] -> [{DiceCountFromOcr}]", CurrentDiceCount, diceCountFromOcr);
CurrentDiceCount = diceCountFromOcr;
}
else if (diceDiff > 2)
{
_logger.LogWarning(" OCR识别到的骰子数[{DiceCountFromOcr}]和计算得出的骰子数[{CurrentDiceCount}]差距较大,舍弃结果", diceCountFromOcr, CurrentDiceCount);
}
var diceDiff = Math.Abs(CurrentDiceCount - diceCountFromOcr);
if (diceDiff is > 0 and <= 2)
{
_logger.LogInformation("可能存在场地牌影响了骰子数[{CurrentDiceCount}] -> [{DiceCountFromOcr}]", CurrentDiceCount, diceCountFromOcr);
CurrentDiceCount = diceCountFromOcr;
}
else if (diceDiff > 2)
{
_logger.LogWarning(" OCR识别到的骰子数[{DiceCountFromOcr}]和计算得出的骰子数[{CurrentDiceCount}]差距较大,舍弃结果", diceCountFromOcr, CurrentDiceCount);
}
}
var alreadyExecutedActionIndex = new List<int>();
var alreadyExecutedActionCommand = new List<ActionCommand>();
@@ -286,6 +290,7 @@ public class Duel
catch (System.Exception ex)
{
_logger.LogError(ex.Message);
Debug.WriteLine(ex.StackTrace);
}
finally
{