作者gR7P4zXH (tpn7gpdx)
看板PCReDive
标题[聊天] 接龙小游戏 python半自动
时间Sun Mar 8 08:45:21 2020
觉得小游戏查表好麻烦,做了一个查表器
附上人权
http://i.imgur.com/vzuo7ru.jpg
# 实验成果
v1
https://youtu.be/IcirpEYB2lY
v2,感谢小精灵改scrcpy
https://youtu.be/Nb9cCh4DmgY
# source code
aHR0cHM6Ly9wYXN0ZWJpbi5jb20vajhNY3F4RGE=
# 实验环境
- Intel(R) Core(TM) i5-6200U CPU @ 2.30GHz
- 12G RAM
- MX500 SSD
- Ubuntu 19.10
# 辨识九宫格图示
OpenCV提供大量函式,为此我们使用了 `matchTemplate` 辨识图示,整体流程如下
1. 切割原始图片成单张图示(icon),大小为106x106px
2. 调整大小至78x78px
3. 用 `matchTemplate` 比对148张既有图示,排序 `min_val`,找出最大值所对应的图
示和ID

得益於Profiling工具的日新月异,我用cProfile分析单执行绪的 python script,发现
最耗时的地方位於`templateMatching`,足足占了整体执行时间97%‧
```bash
~$ python3 -m cProfile -s tottime ./tmp.py
0.7606322765350342
325680 function calls (318751 primitive calls) in 1.289 seconds
Ordered by: internal time
ncalls tottime percall cumtime percall filename:lineno(function)
1287 0.741 0.001 0.741 0.001 {matchTemplate}
28/17 0.162 0.006 0.240 0.014 {built-in method
_imp.create_dynamic}
280 0.045 0.000 0.045 0.000 {built-in method marshal.loads}
2 0.041 0.020 0.041 0.020 {imread}
```
### 全彩转灰阶
试着将全彩图示转换成灰阶再进行比对
```bash
~$ python3 -m cProfile -s tottime ./tmp.py
0.2725179195404053
326034 function calls (319105 primitive calls) in 0.811 seconds
Ordered by: internal time
ncalls tottime percall cumtime percall filename:lineno(function)
1287 0.256 0.000 0.256 0.000 {matchTemplate}
```
看的出 maximum overhead 还是在`templateMatch`,但总执行时间足足少了65%‧
### 缩小图示再比对
将两边要比对的78x78px缩小至26x26px,於是`matchTemplate`让出宝座,整体执行时间
更是来到 0.05s(-80%),图示辨识率也还是维持100%。
```
0.05796694755554199
326071 function calls (319142 primitive calls) in 0.613 seconds
Ordered by: internal time
ncalls tottime percall cumtime percall filename:lineno(function)
28/17 0.153 0.005 0.234 0.014 {built-in method
_imp.create_dynamic}
280 0.046 0.000 0.046 0.000 {built-in method marshal.loads}
2 0.043 0.022 0.043 0.022 {imread}
1287 0.042 0.000 0.042 0.000 {matchTemplate}
1175/1120 0.021 0.000 0.073 0.000 {built-in method
builtins.__build_class__}
```
为了减少执行时间,我们也测试图片大小和辨识准确率关系,程式有做一些改动(印出正
确率、存测试资料),下方数据只是作为 Image size 的选取依据并非实际执行时间。测
试脚本如下
```bash
for i in `seq 78 -2 1`;do icon_size=$i python3 tmp.py; done;
```
只用一张游戏画面图片做测试
icon size | elapsed time (sec)| accurate rate %)
---|---|---
78x78|0.2452|100.0
26x26|0.0758|100.0
24x24|0.0447|100.0
22x22|0.0434|100.0
20x20|0.0390|100.0
18x18|0.0389|88.9
16x16|0.0339|77.8
14x14|0.0473|77.8
12x12|0.0277|66.7
10x10|0.0295|77.8
8x8|0.0248|55.6
6x6|0.0234|55.6
4x4|0.0221|11.1
2x2|0.0210|11.1
看来极限能到20x20px,取20x20的耗时较26x26减少30%
26x26
```
0.0584
326155 function calls (319226 primitive calls) in 0.573 seconds
Ordered by: internal time
ncalls tottime percall cumtime percall filename:lineno(function)
28/17 0.144 0.005 0.221 0.013 {built-in method
_imp.create_dynamic}
280 0.045 0.000 0.045 0.000 {built-in method marshal.loads}
1287 0.043 0.000 0.043 0.000 {matchTemplate}
```
20x20
```
0.0406
326057 function calls (319128 primitive calls) in 0.628 seconds
Ordered by: internal time
ncalls tottime percall cumtime percall filename:lineno(function)
28/17 0.158 0.006 0.242 0.014 {built-in method
_imp.create_dynamic}
280 0.050 0.000 0.050 0.000 {built-in method marshal.loads}
2 0.043 0.021 0.043 0.021 {imread}
1287 0.025 0.000 0.025 0.000 {matchTemplate}
```
不知道为什麽行的通...但是算了

### 使用python的sorted
Python的`sorted`使用名为Timsort的混合式排序演算法,使用`sorted`减少了0.0006秒
的执行时间
```
0.0385->0.0379
```
```python=
# Before
def findIconId(img):
id = None
result = -1
for icon in icons.values():
min_val, max_val, min_loc, max_loc = cv.minMaxLoc(res)
if (result < min_val):
result = min_val
id = icon.id
return id
# After
def findIconId(img):
arr=[]
for icon in icons.values():
res = cv.matchTemplate(resized,icon.img,cv.TM_CCOEFF)
min_val, max_val, min_loc, max_loc = cv.minMaxLoc(res)
arr.append((min_val, icon.id))
arr = sorted(arr, key= lambda x: x[0],reverse=True)
return arr[0][1]
```
### Multithreading
最後手段,但用了反而增加时间,不予采用。
`0.0373->0.0494 secs`
你知道 python 的 multithreading 跟你想像的不一样吗?
:::success
"_Each thread that wants to run must wait for the GIL to be released by the
other thread, which means your multi-threaded Python application is actually
single threaded._"
https://medium.com/practo-engineering/threading-vs-multiprocessing-in-python-7b57f224eadb
:::

### 保险机制
游戏中的过场画面可不能拿来辨识,因此次要设计用一套方法来判断何时该开始辨识
1. 用像素点颜色判断白边存在
2. 侦测白色反光,取图示中心的点做判断
两项测试都通过後才会进行template matching
**valid**
> 
>
>**invalid**
> 
> 
> 
> 
> 
> 
### 辨识韵母
韵母只有一张图要和38张图比对,尺寸小,耗时短,不在此多着墨。
# 选取演算法
这部份没什麽特别,目标就是最高分的图示。以满图监为目标?不会多点几次?
--
※ 发信站: 批踢踢实业坊(ptt.cc), 来自: 111.248.3.243 (台湾)
※ 文章网址: https://webptt.com/cn.aspx?n=bbs/PCReDive/M.1583628323.A.04D.html
※ 编辑: gR7P4zXH (118.161.105.58 台湾), 03/08/2020 08:52:43
1F:推 KParmy: 看不懂你在干嘛 但好像很厉害 推一下 03/08 08:52
2F:推 ikaros35: 我做研究都没那麽认真 跪了 03/08 08:53
3F:推 adamacon: 你的指导教授知道你在作这种东西吗? 03/08 08:56
跑实验闲暇时做的
4F:推 qni1104: 这技术用在游戏上,我只能跪了谢谢大大造福群众 03/08 09:07
5F:推 Jongkook: 三小= = 03/08 09:09
6F:推 r22742557: 不好意思请教一下,你在辨识九宫格图示部分,是使用萤 03/08 09:10
讲完R
7F:嘘 shaodw791017: ? 03/08 09:11
8F:推 CYL009: 我今天流量够了 该睡觉了 03/08 09:11
9F:推 askye546388: 看起来很厉害的样子 03/08 09:11
10F:推 KMSNY: 很好 明天来上班 03/08 09:15
11F:推 amsterdamDK: 三小。。 03/08 09:21
12F:推 aha8877: 先推,免得其他人以为我看不懂 03/08 09:41
13F:推 honey4617912: 嗯嗯我也是这麽想的 03/08 09:48
14F:推 x8s8x8s8x: 偶先推 03/08 09:57
15F:推 dajon: 所以是萤幕辨识+按键精灵吗 03/08 10:02
没有按键精灵
16F:推 sakuravivio: 先推,装懂 03/08 10:03
17F:推 Incredible99: 看不懂你在干嘛 不过你之後要去so-net? 03/08 10:03
比较想去.net折衣服
18F:→ crazycy: 这不就外挂... 03/08 10:09
我自己手动点,不算外挂喔
19F:→ Tiamat6716: 科技的力量 03/08 10:09
20F:推 felixden: 看不懂 03/08 10:12
21F:推 Tamama56: 先推 03/08 10:13
22F:推 otakuxavier: 请问可以把py档放github吗 想clone下来好好研究一下 03/08 10:17
粪扣公开伤眼
23F:推 mifire: sonet:你要来我这里报到了吗 03/08 10:17
24F:推 zodhk01054: 不懂,先推再说 03/08 10:23
25F:推 Terry1984: 太神啦 03/08 10:24
26F:推 pionlang5566: 有没有打算放在 github 开源 03/08 10:29
好
27F:推 a890324: 哇靠 文组看不懂啊 03/08 10:31
28F:推 pionlang5566: 用 numba 会比较快吗 <-出张嘴 03/08 10:33
29F:推 loltrg42972: 科技始终来自人性 03/08 10:33
30F:推 rhythm7321: 推 如果能找想要的押韵就更猛了 03/08 10:44
请开spec
31F:推 sweetmiki: 我觉得你在做坏事 但我看不懂 03/08 10:45
32F:→ smart0eddie: 姆咪 03/08 10:53
33F:推 shinobunodok: 现在打电动都要这麽硬派写实喔 03/08 11:01
34F:推 wsttuub: .......看不懂但先跪再说 03/08 11:13
35F:推 dend930037: 你的指导教授知道这件事吗 03/08 11:17
这是在家搞的
36F:推 gsfate: 这算外挂吗XD 03/08 11:17
37F:推 nutta: 先推免得 03/08 11:20
38F:推 qwert65732: 上次是连点这次是小游戏脚本 某人要高潮了吗 03/08 11:26
泳犬小游戏?
39F:推 roc074: 这跟去so-net没一点关系,原po应该会去做影像辨识的公司吧 03/08 11:28
影像公司泊车小弟
40F:推 bomda: 这就是外挂啊 03/08 11:38
41F:推 paul31788: 推 03/08 11:42
42F:→ CVTaihouKai: 第1行不就是写查表器了 03/08 11:44
43F:推 ptgeorge2: 我只是想打手枪,你给我看这个= = 03/08 12:11
44F:推 frosagen2018: 我也是这麽想的 03/08 12:18
45F:推 DanielHAO: 跟我想得差不多 03/08 12:18
46F:推 x80307: 窝不知道 你再说蛇某 03/08 12:23
47F:→ bightp36936: 现在玩公连这麽硬的吗 03/08 12:44
48F:推 enders346: 太强啦 03/08 12:47
49F:推 kingoflag: 我需要git网址 为了研究 03/08 13:04
怎麽这麽多人知道git
50F:推 js850604: 玩公连先学影像辨识 03/08 13:10
不用学,这没用到理论
51F:推 abjeffop: 嗯嗯 跟我当初想的一样 谢谢付诸行动 03/08 13:17
52F:推 he01023815: 嗯嗯跟我想的差不多 03/08 13:20
53F:推 sismiku: IOTA凸了木有 03/08 13:29
54F:→ sismiku: 发钱辣 03/08 13:29
凸了墓
55F:推 joe1211: 这山小... 03/08 14:02
56F:推 littlestar66: 嗯嗯 跟我当初想的一样 03/08 14:16
57F:推 powerkshs: 你的got hub勒 03/08 14:25
58F:嘘 mikeneko: 讲中文可以吗 03/08 14:31
都蕊咪发搜
59F:推 ruler76818: python。ai辨识 03/08 15:09
60F:推 Raynor: source code 呢? (敲碗 03/08 15:25
站内信
61F:→ NoLimination: 说人话 03/08 15:48
62F:推 duncan1315: 请问有哪些教授有在做upscale的吗?满有兴趣的 03/08 16:13
大佬跑错板了
63F:推 zax5566x2: 请问paper哪里可以找到 03/08 16:15
64F:推 dkchronos: 我需要网址,为了研究用途。03/08 17:03
65F:推 asteea: ...我竟然看的懂 推有心去写 又有心分享成果03/08 17:14
66F:推 lionel20002: scale前可以把边界剪掉 外面那一圈白框对辨识没帮助03/08 17:43
感谢建议,但已达到可用标准,懒得再改
67F:推 mose56789: 瑟瑟发抖03/08 17:47
68F:推 taikobo: 有看有推03/08 18:17
69F:→ b940315: 感觉会被当外挂 还好我打玩了03/08 19:17
70F:推 to9527: 求github XD 03/09 00:03
71F:推 KaiKaiGod: 私! 03/09 00:35
※ 编辑: gR7P4zXH (111.248.3.243 台湾), 03/09/2020 03:20:04
※ 编辑: gR7P4zXH (111.248.3.243 台湾), 03/09/2020 03:30:37
※ 编辑: gR7P4zXH (111.248.3.243 台湾), 03/09/2020 03:57:56
※ 编辑: gR7P4zXH (1.171.87.231 台湾), 03/09/2020 04:49:11
72F:推 y124421473: 你赢了... 03/09 07:58
73F:推 MiRRorX: 果然等着就有神人,太猛了,求站内codeXD 03/09 08:41
74F:推 kevin801117: 太神拉 要是我会还是懒得做 03/10 08:54
75F:推 stocking0: 电脑白痴的我 连怎样弄和用都不知道 03/10 11:07
76F:推 eric910005: 傻眼 03/10 21:23