mirror of
https://github.com/babalae/better-genshin-impact.git
synced 2026-03-15 07:43:20 +08:00
调整浓缩树脂识别范围,解决V4模型无法准确识别浓缩树脂个数的问题 #2185
This commit is contained in:
@@ -6,6 +6,7 @@ using BetterGenshinImpact.Helpers;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using OpenCvSharp;
|
||||
using System;
|
||||
using BetterGenshinImpact.GameTask.AutoPick;
|
||||
|
||||
namespace BetterGenshinImpact.GameTask.AutoDomain.Model;
|
||||
|
||||
@@ -77,7 +78,7 @@ public class ResinStatus
|
||||
if (condensedResinRes.IsExist())
|
||||
{
|
||||
// 找出 icon 的位置 + 25 ~ icon 的位置+45 就是浓缩树脂的数字,数字宽20
|
||||
var condensedResinCountRect = new Rect(crop2.X + condensedResinRes.Right + (int)(20 * assetScale), (int)(37 * assetScale), (int)(70 * assetScale), (int)(24 * assetScale));
|
||||
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();
|
||||
|
||||
@@ -246,7 +246,7 @@ public partial class AutoPickTrigger : ITaskTrigger
|
||||
else
|
||||
{
|
||||
var textMat = new Mat(content.CaptureRectArea.SrcMat, textRect);
|
||||
var boundingRect = TextRectExtractor.GetTextBoundingRect(textMat, out var bin);
|
||||
var boundingRect = TextRectExtractor.GetTextBoundingRect(textMat);
|
||||
// 如果找到有效区域
|
||||
if (boundingRect.X <20 && boundingRect.Width > 5 && boundingRect.Height > 5)
|
||||
{
|
||||
|
||||
@@ -11,12 +11,17 @@ public static class TextRectExtractor
|
||||
/// 从图片中提取文字范围(假定文字从最左边贴边开始,向右连续)
|
||||
/// 结果矩形固定 x=0,y=0,h=原图高度,只计算连续文字宽度。
|
||||
/// </summary>
|
||||
public static Rect GetTextBoundingRect(Mat textMat, out Mat bin)
|
||||
/// <param name="textMat">文字图片</param>
|
||||
/// <param name="min">二值化阈值</param>
|
||||
/// <param name="max">二值化阈值</param>
|
||||
/// <returns></returns>
|
||||
public static Rect GetTextBoundingRect(Mat textMat, double min = 160, double max = 255)
|
||||
{
|
||||
// 转换为灰度图
|
||||
Mat gray = new Mat();
|
||||
Mat gray;
|
||||
if (textMat.Channels() == 3)
|
||||
{
|
||||
gray = new Mat();
|
||||
Cv2.CvtColor(textMat, gray, ColorConversionCodes.BGR2GRAY);
|
||||
}
|
||||
else
|
||||
@@ -25,8 +30,8 @@ public static class TextRectExtractor
|
||||
}
|
||||
|
||||
// 使用阈值160进行二值化处理
|
||||
bin = new Mat();
|
||||
Cv2.Threshold(gray, bin, 160, 255, ThresholdTypes.Binary);
|
||||
using var bin = new Mat();
|
||||
Cv2.Threshold(gray, bin, min, max, ThresholdTypes.Binary);
|
||||
|
||||
// 形态学操作:先腐蚀后膨胀,去除噪点并保持文字完整
|
||||
Mat kernel = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(3, 3));
|
||||
@@ -37,7 +42,46 @@ public static class TextRectExtractor
|
||||
return ProjectionRect(textMat, bin);
|
||||
}
|
||||
|
||||
private static Rect ProjectionRect(Mat textMat, Mat bin)
|
||||
public static Rect GetNumberBoundingRect(Mat textMat, double min = 180, double max = 255)
|
||||
{
|
||||
// 转换为灰度图
|
||||
Mat gray;
|
||||
if (textMat.Channels() == 3)
|
||||
{
|
||||
gray = new Mat();
|
||||
Cv2.CvtColor(textMat, gray, ColorConversionCodes.BGR2GRAY);
|
||||
}
|
||||
else
|
||||
{
|
||||
gray = textMat.Clone();
|
||||
}
|
||||
|
||||
// 使用阈值160进行二值化处理
|
||||
using var bin = new Mat();
|
||||
Cv2.Threshold(gray, bin, min, max, ThresholdTypes.Binary);
|
||||
|
||||
// 形态学操作:直接膨胀
|
||||
Cv2.Dilate(bin, bin, new Mat(), iterations: 2);
|
||||
gray.Dispose();
|
||||
var rect = ProjectionRect(textMat, bin);
|
||||
// 数字后面加点宽度
|
||||
if (rect != new Rect())
|
||||
{
|
||||
var newWidth = rect.Width + 10;
|
||||
rect.Width = newWidth > textMat.Width ? textMat.Width : newWidth;
|
||||
}
|
||||
|
||||
return rect;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 投影, 获取连续文字的边界矩形
|
||||
/// </summary>
|
||||
/// <param name="textMat"></param>
|
||||
/// <param name="bin"></param>
|
||||
/// <param name="maxGap">允许的最大连续空列数</param>
|
||||
/// <returns></returns>
|
||||
public static Rect ProjectionRect(Mat textMat, Mat bin, int maxGap = 30)
|
||||
{
|
||||
// 投影:对行做 ReduceSum,得到 1 x width 的列和
|
||||
using var projection = new Mat();
|
||||
@@ -45,7 +89,6 @@ public static class TextRectExtractor
|
||||
int width = projection.Cols;
|
||||
projection.GetArray(out int[] colSums);
|
||||
|
||||
int maxGap = 30; // 允许的最大连续空列数
|
||||
int gapCount = 0;
|
||||
int lastNonEmpty = -1;
|
||||
|
||||
@@ -66,7 +109,7 @@ public static class TextRectExtractor
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (lastNonEmpty == -1)
|
||||
{
|
||||
// 没有检测到文字
|
||||
@@ -76,4 +119,4 @@ public static class TextRectExtractor
|
||||
Rect boundingRect = new Rect(0, 0, lastNonEmpty, textMat.Height);
|
||||
return boundingRect;
|
||||
}
|
||||
}
|
||||
}
|
||||
Submodule Test/BetterGenshinImpact.UnitTest/Assets updated: 3df550ad83...e644666398
@@ -11,19 +11,19 @@ namespace BetterGenshinImpact.UnitTest.CoreTests.RecognitionTests.OCRTests
|
||||
|
||||
public PaddleOcrService Get(string cultureInfoName = "zh-Hans", string version = "V5")
|
||||
{
|
||||
return _paddleOcrServices.GetOrAdd(cultureInfoName, name =>
|
||||
return _paddleOcrServices.GetOrAdd(cultureInfoName + "_" + version, _ =>
|
||||
{
|
||||
lock (_paddleOcrServices)
|
||||
{
|
||||
if (version == "V5")
|
||||
{
|
||||
return new PaddleOcrService(new BgiOnnxFactory(new FakeLogger<BgiOnnxFactory>()),
|
||||
PaddleOcrService.PaddleOcrModelType.FromCultureInfo(new CultureInfo(name)) ?? PaddleOcrService.PaddleOcrModelType.V5);
|
||||
PaddleOcrService.PaddleOcrModelType.FromCultureInfo(new CultureInfo(cultureInfoName)) ?? PaddleOcrService.PaddleOcrModelType.V5);
|
||||
}
|
||||
else if (version == "V4")
|
||||
{
|
||||
return new PaddleOcrService(new BgiOnnxFactory(new FakeLogger<BgiOnnxFactory>()),
|
||||
PaddleOcrService.PaddleOcrModelType.FromCultureInfoV4(new CultureInfo(name)) ?? PaddleOcrService.PaddleOcrModelType.V4);
|
||||
PaddleOcrService.PaddleOcrModelType.FromCultureInfoV4(new CultureInfo(cultureInfoName)) ?? PaddleOcrService.PaddleOcrModelType.V4);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -21,12 +21,14 @@ namespace BetterGenshinImpact.UnitTest.GameTaskTests.AutoDomainTests
|
||||
this.paddle = paddle;
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(@"AutoDomain\SelectRevitalization.png", 21, 0, 2, 1)]
|
||||
[InlineData(@"AutoDomain\SelectRevitalizationOcrV4.png", 11, 0, 1, 149, "V4")]
|
||||
/// <summary>
|
||||
/// 测试识别四种树脂数量,数量应正确
|
||||
/// </summary>
|
||||
[Theory]
|
||||
[InlineData(@"AutoDomain\SelectRevitalization.png", 21, 0, 2, 1)]
|
||||
[InlineData(@"AutoDomain\SelectRevitalizationOcrV4.png", 11, 0, 1, 149, "V4")]
|
||||
[InlineData(@"AutoDomain\SelectRevitalizationOcrV4_NSSZ1.png", 20, 1, 1, 0, "V4")]
|
||||
[InlineData(@"AutoDomain\SelectRevitalizationOcrV4_NSSZ1.png", 20, 1, 1, 0)]
|
||||
public void RecogniseFromRegion_ResinStatusShouldBeRight(string screenshot1080p, int originalResinCount, int fragileResinCount, int condensedResinCount, int transientResinCount, string ocrVersion = "V5")
|
||||
{
|
||||
//
|
||||
|
||||
Reference in New Issue
Block a user