Rehcramon / MasterDuelCardTranslator

A tool for translating card details in Yu-Gi-Oh! Master Duel.
GNU General Public License v3.0
63 stars 15 forks source link

算法逻辑(卡名匹配)改进建议 #22

Open YoungHector opened 2 years ago

YoungHector commented 2 years ago

hello, 非常感谢您的贡献!有幸阅读了您的源码,我对卡名匹配的环节提出如下建议: 考虑到ygo目前卡片数量是有限的,并且量级不大(短期内不超过20k),因此卡名信息可以直接载入到内存中,然后通过文本相似度(例如编辑距离)来进行匹配,如下:


import time 
import Levenshtein

target = "Blackwing - Silverwind the Ascendant"
query = "Blackwing - Salverwind the Ascen"

start_time = time.time()
for i in range(11000):
    Levenshtein.distance(target, query) # 计算编辑距离,越小说明越相似。
print(time.time() - start_time)

上述11000次(模拟卡片全集的数量)循环计算,约16毫秒可执行完成,因此用户几乎无感。可以每次对输入的query(ocr结果),计算对一万多张牌的编辑距离,并排序,找到最接近的卡片标准名称,然后用标准名称进行查库。这样可以极大缓解ocr错误带来的查询不到结果的问题。同时,编辑距离是一个时间复杂度很低的算法,您可以测试一下对cpu的压力,应该不大。

Rehcramon commented 2 years ago

十分感谢你的建议。

目前以我的经验来看,取游戏中滚动展示的卡名进行OCR时,我基本没有再遇见因为OCR错误的情况了。这个问题是最开始直接用Tesseract导致识别能力不佳的时候会出现的,但是我通过对图片进行简单地编辑之后就再也没出现过了。当然可能是我测试的卡很少。如果你有着任何case,欢迎再联系我,我会重新评估当前的准确率问题。 但是,当前OCR需要等待卡名滚动完全。而这样的时候实际上会有着大量的等待时间。我有考虑过识别卡图上面的卡名,它是完整的卡名,并且是写在卡上的卡名。由于它的排版方式比较特别,导致识别率低下。在这种情况下,如果你的方案可以通过“距离”来进行匹配,我觉得效果会比当前的方案要好很多。

所以如果要使用你的方案,我会优先把它与识别卡图上的卡名的方案进行结合,而不会与当前的方案进行结合。 我接下来更新的重点会放在改进识别方案上,你的这个issue对我的帮助非常大。再次感谢。

YoungHector commented 2 years ago

如果可以解决等待时间的这个问题,那太好了。我想到,在文本相似度匹配的基础上,如果有几张卡名相似会错判,可以增加一些图片方面的信息来辅助判断。例如我注意到您的代码中有如下操作:

cardname = pytesseract.image_to_string(ImageOps.invert(Image.open('screenshot.png').convert('L')), lang='eng',
                                               config='--psm 7')[:-1]

Image.open('screenshot.png')之后,转换成黑白之前,您可以对截图当中卡图(正方形)的部分进行粗略的切分(我没仔细看您关于图像处理的部分,如果有找到卡图的步骤的话),比如切成3 * 3,9个格子,计算每个格子像素点的平均值,这个操作是省力的。于是获得了一个长度为9的list, 每个元素代表按顺序某个区块的平均颜色. 另一边,标准卡图可以进行离线的计算,每张卡牌存储一个长度为9的list. 这样可以通过欧式距离等方式,得到卡图颜色的相似度。结合卡图颜色与文本编辑距离等,可以缓解名称相似的卡牌的识别问题。希望上述思路可以帮到您。

Rehcramon commented 2 years ago

这个思路看上去确实很好,可以通过卡图来进行识别。目前暂时没有做卡图的原因:一是我的技术还不行,希望另一位作者可以帮忙处理一下;二来则是有闪卡的问题,卡图在闪烁的时候会有着一定的改变,导致很难识别。

之后如果要做卡图识别的话,我会参考你的这个思路的。十分感谢。