玩明日方舟半年了,一直苦于没有一个好用的公招计算器,因为自己懒得去记各种稀有的 tag 组合,每次又要切出游戏打开三方的计算器再手动选择 tag 组合,非常麻烦,于是就自己写了这么一个小工具。其最大的特点就是可以从截图自动获取当前的 tags,省去了每次手动选择的过程,相对来说就更方便了一些。

图片识别

首先要解决的问题就是从公开招募页面的截图中识别到 5 个 tag 的内容。

因为本人不会图像识别相关技术,于是采用了一个可能是最笨的办法,逐行像素去识别颜色...

公开招募

首先从截图中测量得到 tag 未被选中时,其背景色的 RGB 值为 (49,49,49)

设截图的长和高分别为 xy,取长的一半命名为 half_x

从截图最下方正中间 (half_x, y) 开始,逐行向上遍历,如颜色与 tag 背景色相同则说明此行为公招页面第二行 tag 的底部,具体为 5 号 tag 的底部(从左到右从上到下依次命名 1 - 5 号),(为了防止 tag 边缘模糊影响判断,此边缘坐标及以下获取到的边缘坐标,均向 tag 中心偏移 2 - 5 个像素),命名为 bottom_2

从该点 (half_x, bottom_2) 分别再向左、右、上、三个方向遍历,遇到颜色与背景色不同,说明找到了 tag 5 的左、右以及第二行 tag 的上边缘,命名为 tag5_lefttag5_righttop_2。这样 tag 5 就可以被划分出来,四边(左、上、右、下)分别为 (tag5_left, top_2, tag5_right, bottom_2)

继续从 (tag5_left, bottom_2) 向左遍历,找到与背景色相同即为 tag 4 右边缘 tag4_right,同样方法找到左边缘 tag4_right,tag 4 的四边即为 (tag4_left, top_2, tag4_right, bottom_2)

(tag4_left, top_2) 向上,找到与背景色相同的第一行 tag 底部边缘 bottom_1,继续向上与背景色不同则为第一行 tag 顶边缘 top_1。此时 tag 1 和 tag 2 也就可以确定了,分别为 (tag4_left, top_1, tag4_right, bottom_1)(tag5_left, top_1, tag5_right, bottom_1)

最后,从 tag 2 右边缘向右,找到 tag 3 的左右边 tag3_lefttag3_right,最后一个 tag 也就确定了 (tag3_left, top_1, tag3_right, bottom_1)

将 5 个标签截取出来之后,通过 OCR 识别标签文字。最开始我使用的是 Tesseract-OCR,但是即使对图片进行灰度处理、二值化等操作,识别效率依然偏低,无法使用。后来我在「百度AI开放平台」找到了百度的文字识别接口,其 「通用文字识别」的免费版拥有 50000次/天 的调用量,且识别准确率相当高,于是最终就采用它来进行识别。

干员筛选

干员数据表

首先要获取干员信息,数据来源为 「着迷网」明日方舟wiki 的干员数据表。主要爬取的信息有「干员代号」、「星级」、「标签」,再从「获取途径」中筛选出包含「公开招募」关键词的干员,整理保存为数据库。

干员数据库

筛选时使用 Python 的 combinations() 方法,从 5 个 tag 中分别抽取三个、两个、一个进行排列组合,再用每个组合去筛选该组合是否为某个干员 tag 的子集,如果满足条件则将该干员及其当前 tag 组合保存至结果内。

如果当前 tag 组合有多名干员符合,还要根据干员星级进行排序。并设置一个标记 gold_flag,如果存在某个 tag 组合仅包含 4 星及以上干员,则此标记为真,最后输出结果时提醒存在稀有 tag。

还有一个需要注意的地方就是「高级资深干员」,仅当此标签存在时才能出现 6 星干员。所以在之前保存数据是将 6 星干员分开储存,仅当有此标签时再从 6 星干员中进行筛选。

程序调用

由于 iOS 的限制,我能想到的方法只有通过「快捷指令」进行调用,首先获取系统中最新一张截图,对其进行 Base64 编码,在服务端搭建一个 RESTful API,接收截图,处理完成后再返回结果。

快捷指令

经过研究后发现,使用 iOS 辅助功能中的「辅助触控」,能够更快速地完成对快捷指令的调用。

首先在「设置」-「辅助功能」-「辅助功能快捷键」将连按三下主屏幕按钮设置为「辅助触控」来快速启用小白点(本人使用 iPhone 8,iPhone X 及后续无 home 按钮的机型视具体情况设置)。

再返回「辅助功能」,在「触控」-「辅助触控」里,将「单点」操作设置为「SIRI 快捷指令」中我们做好的捷径;将「轻点两下」操作设置为「截屏」。

经过上面的设置,我们可以在游戏中通过连按三次 home 键呼出小白点。当需要公开招募时,先双击小白点截屏,再单击即可运行快捷指令,获取公招结果。

结果


大致流程就是这样,代码写的太烂,暂时就不开源了,调用地址目前也不会公开,因为还有好多 bug(x,等什么时候完善了再放出来吧。还有关于 Android 端,理论上 Android 端是可以开个悬浮窗一键截图在本地处理并返回结果的,但是本人不会写 Android,如果谁有兴趣可以尝试以下。

Last modification:May 14th, 2020 at 11:43 am
If you think my article is useful to you, please feel free to appreciate