mirror of
https://github.com/babalae/better-genshin-impact.git
synced 2026-05-25 10:05:49 +08:00
* chore: add AGENTS.md to .gitignore * feat(config): 新增 AllowDuplicateChar OCR配置项 * refactor(ocr): Rec 暴露protected成员、提取RunInference、支持AllowDuplicateChar * feat(ocr): 打通 AllowDuplicateChar 参数链 PaddleOcrService → Rec * feat(ocr): OcrUtils 新增 CreateLabelDict/CreateWeights 工具方法 * feat(helpers): 新增 LruCache 缓存工具类 * feat(ocr): 新增 RecMatch DP模糊匹配识别器 * test(helpers): 新增 LruCache 单元测试 * test(ocr): 新增 RecMatch.GetTarget / CreateLabelDict 单元测试 * fix(ocr): 修复 RecMatch 中权重矩阵乘法的使用方式 * refactor(ocr): 合并 RecMatch 到 Rec,提取可测试静态方法,补充单元测试 将 RecMatch 子类合并到 Rec 中,消除继承关系和重复的批处理逻辑(提取 RunBatch<T>)。 将 GetTarget 核心逻辑和 GetMaxScoreDP 提取为 OcrUtils 静态方法以便独立测试。 重命名测试文件并新增 16 个单元测试覆盖 MapStringToLabelIndices、GetMaxScoreDP、CreateWeights。 * feat(ocr): 将 Rec.RunMatch 暴露给 JS 引擎和内部 C# 代码 新增 IOcrMatchService 接口,提供基于 DP 模糊匹配的 OcrMatch/OcrMatchDirect 方法, 返回 0~1 置信度分数。PaddleOcrService 实现该接口,OcrFactory.PaddleMatch 保证 非 null 返回(引擎不支持时自动回退到普通 OCR + 编辑距离字符串比较)。 BvPage 新增 OcrMatch/WaitForOcrMatch 供 JS 脚本使用,阈值可通过配置调整。 * feat(ui): 为 OCR 配置添加允许重复字符和模糊匹配阈值的设置项 在通用设置页 OCR 配置区域新增两个控件: - 允许连续重复字符(AllowDuplicateChar)开关 - OCR模糊匹配阈值(OcrMatchDefaultThreshold)输入框 * fix: 修复 PR #2799 代码审查中发现的多项问题 - 修复 Rec.cs 空文本时 score/sb.Length 除零产生 NaN - 修复 BvPage.cs rect==default 时同一对象被双重 Dispose - 移除 Rec.cs Finalizer 避免 GC 线程加锁死锁 - 移除 CacheHelper WeakKey 无效功能,简化为直接 Dictionary 查找 - 添加 weights 数组长度与模型输出维度校验 - 修复 CreateLabelDict 空格标签索引冲突 - 修复 GetMaxScoreDP availableCount=0 除零 - 修复 OcrMatchFallbackService Contains 大小写敏感 - 修复 BvPage.cs DefaultRetryInterval=0 除零 - 添加 OcrMatchDefaultThreshold [0,1] 范围约束 - 提取 PaddleOcrService BGRA→BGR 转换辅助方法 - 使用 Interlocked.CompareExchange 修复 OcrFactory Fallback 线程安全 - 增大 LruCacheTests BuilderTest TTL 裕量避免 CI 不稳定 - 更新 .gitignore 注释 * fix: 修复 OcrMatch 归一化分母导致多区域匹配分数过低的 bug,改进 UI - 修复 GetMaxScoreFlat 中 availableCount 使用非空图像数作为分母, 导致多文字区域场景下匹配分数被过度稀释的问题,改为使用 target.Length - AllowDuplicateChar 设置项添加"需重新加载OCR引擎"的提示 - OCR模糊匹配阈值控件从 TextBox 改为 Slider + 数值显示 - 移除 Det 类中有问题的 finalizer(含锁的析构函数可能导致死锁) - 补充多区域场景的单元测试 * feat(ocr): 添加队伍切换时使用OcrMatch模糊匹配的选项和相关配置 * fix(ui): 更新匹配成功阈值默认值为 0.8 * fix(ocr): 修复队伍切换逻辑中的空值处理和优化代码结构 * refactor: 简化 LruCache,移除弱引用支持和 Builder 模式 - 移除有 TOCTOU bug 的 WeakReference 支持(且无实际使用方) - CacheItem 类改为 ValueTuple 减少堆分配 - 无过期时不再赋值 DateTime.MaxValue,过期检查短路跳过 - 移除仅剩两参数的 LruCacheBuilder,直接使用构造函数 * fix(ocr): 修复 CreateWeights 中空格字符权重写入错误索引的 bug 复用 CreateLabelDict 构建索引映射,确保空格映射到 labels.Count+1, 与 CreateLabelDict 保持一致。添加对应测试用例。 * fix(ocr): 修复 GCHandle.Alloc 失败时 finally 中 Free 掩盖原始异常的问题 * fix(ocr): 添加队伍选择按钮存在性检查,避免 PartySetupFailedException * fix(ocr): 调整 OcrMatchDefaultThreshold 的 TickFrequency 为 0.01 * fix(ocr): 修复区域裁剪逻辑,确保裁剪尺寸不为负值 * fix(ocr): 优化字符置信度提取逻辑,直接按目标字符索引查找置信度 * fix(ocr): 修正变量命名以保持一致性,调整方法名大小写 * fix(ocr): 修改 CreateWeights 方法以使用标签字典和标签计数,优化权重创建逻辑 * fix(ocr): 更新 OCR 置信度阈值设置,确保阈值范围为 0.01 到 0.99,并优化相关逻辑
165 lines
4.8 KiB
C#
165 lines
4.8 KiB
C#
using System;
|
||
using BetterGenshinImpact.Core.Recognition;
|
||
using BetterGenshinImpact.Model;
|
||
using CommunityToolkit.Mvvm.ComponentModel;
|
||
|
||
namespace BetterGenshinImpact.Core.Config;
|
||
|
||
|
||
[Serializable]
|
||
public partial class OtherConfig : ObservableObject
|
||
{
|
||
//调度器任务和部分独立任务,失去焦点,自动激活游戏窗口
|
||
[ObservableProperty]
|
||
private bool _restoreFocusOnLostEnabled = false;
|
||
//自动领取派遣任务城市
|
||
[ObservableProperty]
|
||
private string _autoFetchDispatchAdventurersGuildCountry = "无";
|
||
//服务器时区偏移量
|
||
[ObservableProperty]
|
||
private TimeSpan _serverTimeZoneOffset = TimeSpan.FromHours(8);
|
||
[ObservableProperty]
|
||
private AutoRestart _autoRestartConfig = new();
|
||
//锄地规划
|
||
[ObservableProperty]
|
||
private FarmingPlan _farmingPlanConfig = new();
|
||
|
||
[ObservableProperty]
|
||
private Miyoushe _miyousheConfig = new();
|
||
//OCR配置
|
||
[ObservableProperty]
|
||
private Ocr _ocrConfig = new();
|
||
|
||
|
||
public partial class AutoRestart : ObservableObject
|
||
{
|
||
[ObservableProperty]
|
||
private bool _enabled = false;
|
||
|
||
//调度器任务连续异常退出几次任务自动重启
|
||
[ObservableProperty]
|
||
private int _failureCount = 5;
|
||
|
||
//是否同时重启游戏,需开启首页启动配置:同时启动原神、自动进入游戏,此配置才会生效
|
||
[ObservableProperty]
|
||
private bool _restartGameTogether = false;
|
||
|
||
//锄地脚本,如果打架次数不一致,则判定任务失败。
|
||
[ObservableProperty]
|
||
private bool _isFightFailureExceptional = false;
|
||
|
||
//任何追踪任务,未走完全路径结束,视为失败。
|
||
[ObservableProperty]
|
||
private bool _isPathingFailureExceptional = false;
|
||
|
||
}
|
||
|
||
public partial class Miyoushe : ObservableObject
|
||
{
|
||
|
||
//cookie
|
||
[ObservableProperty]
|
||
private string _cookie = "";
|
||
|
||
//与调度器日志处相互同步cookie
|
||
[ObservableProperty]
|
||
private bool _logSyncCookie = true;
|
||
|
||
}
|
||
public partial class MiyousheDataSupport : ObservableObject
|
||
{
|
||
[ObservableProperty]
|
||
private bool _enabled = false;
|
||
|
||
//日精英上限
|
||
[ObservableProperty]
|
||
private int _dailyEliteCap = 400;
|
||
|
||
//日小怪上限
|
||
[ObservableProperty]
|
||
private int _dailyMobCap = 2000;
|
||
}
|
||
public partial class FarmingPlan : ObservableObject
|
||
{
|
||
|
||
|
||
[ObservableProperty]
|
||
private MiyousheDataSupport _miyousheDataConfig = new();
|
||
|
||
[ObservableProperty]
|
||
private bool _enabled = false;
|
||
|
||
//日精英上限
|
||
[ObservableProperty]
|
||
private int _dailyEliteCap = 400;
|
||
|
||
//日小怪上限
|
||
[ObservableProperty]
|
||
private int _dailyMobCap = 2000;
|
||
|
||
}
|
||
|
||
public partial class Ocr : ObservableObject
|
||
{
|
||
/// <summary>
|
||
/// PaddleOCR模型配置
|
||
/// </summary>
|
||
[ObservableProperty]
|
||
private PaddleOcrModelConfig _paddleOcrModelConfig = PaddleOcrModelConfig.V4Auto;
|
||
|
||
/// <summary>
|
||
/// 允许OCR结果中出现连续重复字符(关闭CTC重复字符折叠)
|
||
/// </summary>
|
||
[ObservableProperty]
|
||
private bool _allowDuplicateChar;
|
||
|
||
/// <summary>
|
||
/// 切换队伍时使用 OcrMatch 模糊匹配代替正则表达式匹配
|
||
/// </summary>
|
||
[ObservableProperty]
|
||
private bool _useOcrMatchForPartySwitch = true;
|
||
|
||
/// <summary>
|
||
/// OcrMatch 模糊匹配的默认阈值 (0~1),分数 ≥ 阈值视为匹配成功
|
||
/// </summary>
|
||
[ObservableProperty]
|
||
private double _ocrMatchDefaultThreshold = 0.8;
|
||
|
||
partial void OnOcrMatchDefaultThresholdChanged(double value)
|
||
{
|
||
if (value is <= 0 or > 1)
|
||
{
|
||
OcrMatchDefaultThreshold = Math.Clamp(value, 0.01, 1);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// PaddleOCR 识别置信度阈值 (0~1),低于此阈值的字符将被过滤
|
||
/// </summary>
|
||
[ObservableProperty]
|
||
private double _paddleOcrThreshold = 0.5;
|
||
|
||
partial void OnPaddleOcrThresholdChanged(double value)
|
||
{
|
||
if (value is < 0 or >= 1)
|
||
{
|
||
PaddleOcrThreshold = Math.Clamp(value, 0, 0.99);
|
||
}
|
||
}
|
||
}
|
||
|
||
//public partial class OtherConfig : ObservableObject
|
||
|
||
/// <summary>
|
||
/// 游戏语言名称
|
||
/// </summary>
|
||
[ObservableProperty]
|
||
private string _gameCultureInfoName = "zh-Hans";
|
||
|
||
/// <summary>
|
||
/// BGI界面语言名称
|
||
/// </summary>
|
||
[ObservableProperty]
|
||
private string _uiCultureInfoName = "zh-Hans";
|
||
}
|