深度解析:AzurLaneAutoScript 中 OCR 识别管线的像素级博弈

📅 2026/8/17 18:27:16
深度解析:AzurLaneAutoScript 中 OCR 识别管线的像素级博弈
深度解析AzurLaneAutoScript 中 OCR 识别管线的像素级博弈【免费下载链接】AzurLaneAutoScriptAzur Lane bot (CN/EN/JP/TW) 碧蓝航线脚本 | 无缝委托科研全自动大世界项目地址: https://gitcode.com/gh_mirrors/az/AzurLaneAutoScriptAzurLaneAutoScriptALAS是碧蓝航线自动化脚本OCR 子系统是它读取油量、金币、活动 PT 等实时数值的眼睛。本文想回答一个核心问题一套纯本地、跨中英日台四服的文字识别管线是如何在像素层面逐层做工程取舍把误读率压低到足以支撑自动决策的水平的一次油量误读引发的追问用过 ALAS 的人可能都有过类似的困惑日志里明明显示OCR_OIL: 1234脚本却判定为油量不足而停手。究其原因多半不是模型太笨而是画面本身变了——游戏在弹窗、夜间模式或部分界面下会给数值区域叠一层半透明遮罩原本接近白色的字体被压成灰暗色识别随之失真。这个细节暴露了识别管线的第一个设计前提OCR 的输入不是整张截图而是按区域裁剪、按颜色过滤后的二值图。管线把像素问题前置解决而不是把期望寄托在模型的泛化能力上。代码在module/base/utils.py的extract_letters中完成这一转换——先计算图像与目标字体颜色之间的色差再做阈值缩放最终字体变黑、背景变白。关键在于目标字体颜色是一个可配置参数。module/campaign/campaign_status.py里对油量的读取逻辑展示了这一点先用一个颜色探针判断当前 UI 是否被黑色遮罩覆盖再据此选择不同的letter参数——遮罩前用 (247, 247, 247)遮罩后用 (165, 165, 165)。一句话识别前先问一句画面处于什么状态再决定用哪套颜色基准。预处理把问题翻译成模型能答的题从实现层面来看module/ocr/ocr.py中Ocr类把识别拆成三个固定步骤pre_process裁剪颜色过滤、模型推理、after_process文本后处理。这套流水线让识别这件事变成可插拔的组合业务方只关心给我数值不必关心模型内部。为什么这里要这么做因为直接对原图推理会带来两个失控变量一是背景噪点会干扰注意力二是模型需要覆盖的字符形态被无谓放大。预处理本质上是用确定性算法消化不确定性——把可能出现的颜色差异、背景花纹全部抹平只留下黑底白字代码实现上是白底黑字的最简信号。工程上的回报是模型可以做得更小、推理更快同时把失败模式收敛到颜色基准选错这一种可排查的问题上。字符集白名单让模型闭卷考试预处理解决看得清接下来要解决读得准。ALAS 的做法很直接为每次识别划定候选字符集。Digit类默认只允许0123456789IDSB这 15 个字符参与预测PtOcr则限定为X0123456789。字符集白名单在推理前通过set_cand_alphabet注入模型把多分类问题临时降维成小分类问题——本质上是让模型闭卷考试不许它乱答。这还不够。数字识别最经典的坑是形近字I 与 1、D 与 0、S 与 5、B 与 8。模型再准也难免在这种地方翻车因此Digit的后处理干脆做规则纠错把上述符号无条件映射为数字即便after_process阶段识别为 I23 也会被规整成 123。result result.replace(I, 1).replace(D, 0).replace(S, 5) result result.replace(B, 8)由此衍生出一族语义化的 OCR 子类DigitCounter负责解析14/15这种剩余次数格式并返回三元组当前/剩余/总数Duration把01:30:00解析成timedelta。业务语义被塞进了 OCR 对象本身上层模块拿到的永远是强类型数据而不是需要二次解析的字符串——这是整个子系统最顺手的设计。五套模型的登记簿按需加载的注册表多语言支持在工程上意味着多套模型。module/ocr/models.py中的OcrModel用cached_property维护了五套模型面向游戏数字字体的azur_lane、azur_lane_jp面向繁中的tw、日文的jp以及兜底全字符集的cnocr。每套模型标注了字体来源、字符集大小与验证准确率如azur_lane为 99.43%。值得注意的设计细节是懒加载模型不随进程启动而加载而是在第一次被访问时才从./bin/cnocr_models/目录装载。这对内存与启动时间都是决定性的——五套 densenet 模型同时驻留内存是不可接受的而脚本日常只用到其中一两套。注册表把模型选择从业务代码里抽离业务侧只通过lang参数azur_lane 等间接引用服务端服务器类型还能自动切换语言模型module/ocr/ocr.py中针对 jp 服务器的分支。对比维度单一大而全模型多套专用小模型首帧延迟低模型常驻较高懒加载单次推理耗时较高显著更低内存占用恒定高位按需占用识别准确率泛化但易混淆领域内更稳把推理搬进独立进程RPC 架构与断线降级OCR 最重的资源是模型推理而 ALAS 的主循环是高频截图决策。如果让模型推理与截图循环共享一个进程一次推理阻塞就可能拖垮整个自动化节奏。module/ocr/rpc.py给出的答案是把推理服务化通过 zerorpc 起一个独立的 OCR 服务进程主程序通过ModelProxy代理远程调用。这套设计的点睛之笔是优雅降级。ModelProxy内部维护一个online状态每次调用若失败自动置为离线并回退到本地直连模型OCR_MODEL.__getattribute__(lang).ocr(...)。也就是说OCR 服务进程宕了脚本不会崩只是回到慢一点的本地推理模式。对于半夜无人值守的自动化场景这种容错策略的价值怎么强调都不过分。从性能角度看RPC 传输走 pickle 序列化图像以img_fp.dumps()打包发送——CPU 推理留在服务端客户端只承担序列化开销整体权衡对延迟敏感的主循环更友好。取舍清单把工程决策摊开看用颜色过滤替代通用预处理准确但脆弱UI 改版或遮罩变化需人工调整参数换取的是模型体积与推理速度。用字符白名单压缩搜索空间把数字识别从 6000 类cnocr 全集压到十几个类代价是复用性下降每个场景要声明自己的字母表。懒加载换内存启动变快、内存可控但首次触发某语言识别时有秒级延迟需在业务层容忍。RPC 服务化换隔离性进程崩溃不连坐主循环但多一层序列化与网络开销且要求部署环境支持额外端口。一言以蔽之这套子系统从头到尾贯彻同一思路把能确定的用代码确定把不能确定的交给小模型把兜底交给降级路径。通用 OCR 追求什么都认识ALAS 的 OCR 追求在已知领域内答对后者的工程产出显然更适合自动化决策。把黑盒打开可复现的验证手段若想亲自验证某次误读的成因有两件事可以做。其一临时打开Ocr类的SHOW_LOG默认开启日志会打印每次识别的耗时与原始结果可用来对比预处理前后结果差异其二调用cnocr.debug(image_list)该方法会把喂给模型的二值化图片原样弹出module/ocr/al_ocr.py直接肉眼确认预处理是否把字看得足够清楚。若二值图里数字残缺问题在letter/threshold参数若二值图清晰但结果仍错问题才在模型或字符集。注意修改模型参数后需重启后端进程才能生效因为模型实例被cached_property缓存排查时可参照config/下的运行日志定位错误来源。结语回看这套识别管线它给自动化里的感知模块提供了一个颇具参考价值的样板感知不是追求无所不能而是围绕已知场景收缩问题空间——预处理消化颜色变化白名单压缩类别空间后处理修正残余错误RPC 提供隔离与容错。每一层都在用一点点领域知识换取确定性最终把识别从不可控的模型黑盒改造成可观测、可调参、可降级的工程组件。对于想为项目做贡献的开发者module/ocr/恰好是入口门槛最低、收益最直观的模块补充某个界面的letter参数、为新字体训练一版小模型都是能立刻改善千名用户日常体验的改动。【免费下载链接】AzurLaneAutoScriptAzur Lane bot (CN/EN/JP/TW) 碧蓝航线脚本 | 无缝委托科研全自动大世界项目地址: https://gitcode.com/gh_mirrors/az/AzurLaneAutoScript创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考