最近微信的(de)跳一跳小程序火了(le/liǎo)一把,所以(yǐ)前天也(yě)更新了(le/liǎo)微信玩了(le/liǎo)幾盤,最多手動到(dào)200左右就(jiù)不(bù)行了(le/liǎo)。
後來(lái)準備用代碼寫個(gè)輔助工具,上(shàng)Github一查,已經有人(rén)做出(chū)來(lái)了(le/liǎo),17年12月29号的(de)項目,不(bù)到(dào)5天差不(bù)多5K的(de)stars,以(yǐ)後還會更多,簡直可怕。
github.com/wangshub/we…
具體思路都差不(bù)多:
- 用adb調試手機,獲取截圖;
- 從截圖中識别棋子(zǐ)和(hé / huò)目标塊的(de)中心點位置;
- 根據距離計算長按時(shí)間,系數和(hé / huò)屏幕分辨率相關;
- 用adb模拟長按,完成跳躍。
唉,多麽可惜,錯過了(le/liǎo)一個(gè)好項目。
既然别人(rén)已經實現了(le/liǎo),那就(jiù)嘗試點不(bù)一樣的(de),用 深度學習 解決一下。
基本思路
基本流程類似,唯一的(de)區别在(zài)于(yú)如何獲取棋子(zǐ)和(hé / huò)目标塊的(de)中心位置。
假如長按時(shí)間隻取決于(yú)棋子(zǐ)和(hé / huò)目标塊的(de)水平位置,那麽隻需要(yào / yāo)知道(dào)它們水平方向上(shàng)的(de)坐标即可。
可以(yǐ)看作一個(gè) 物體檢測 問題,檢測出(chū)截圖中的(de)棋子(zǐ)等物體,這(zhè)裏假設共包含七類物體:
- 棋子(zǐ):chess
- 彩蛋塊:包括污水 waste、魔方 magic、商店 shop、音樂盒 music
- 普通塊:包括矩形塊 rect、圓形塊 circle
模型實現
我手動标注了(le/liǎo)500張截圖,基于(yú)ssd_mobilenet_v1_coco
模型和(hé / huò)TensorFlow
物體檢測API,訓練好的(de)模型跑起來(lái)是(shì)這(zhè)麽個(gè)結果。
可以(yǐ)看到(dào)截圖中的(de)棋子(zǐ)、魔方、矩形塊、圓形塊都被檢測了(le/liǎo)出(chū)來(lái),每個(gè)檢測結果包括三部分内容:
- 物體位置,用矩形标注,對應四元組 ymin、xmin、ymax、xmax;
- 物體類别,爲(wéi / wèi)以(yǐ)上(shàng)七類中的(de)一種;
- 檢測置信度,越高說(shuō)明模型對檢測結果越有把握。
這(zhè)不(bù)僅僅是(shì)簡單的(de)規則檢測,而(ér)是(shì) 真正看到(dào)了(le/liǎo)截圖中共有哪幾個(gè)物體,以(yǐ)及每個(gè)物體分别是(shì)什麽。
所以(yǐ)接下來(lái),就(jiù)隻需從檢測結果中取出(chū)棋子(zǐ)的(de)位置,以(yǐ)及最上(shàng)面一個(gè)非棋子(zǐ)物體,即目标塊的(de)位置。
有了(le/liǎo)物體的(de)邊界輪廓,取中點即可得到(dào)棋子(zǐ)和(hé / huò)目标塊的(de)水平坐标,這(zhè)裏進行了(le/liǎo)歸一化,即屏幕寬度爲(wéi / wèi)1,距離在(zài)0至1之(zhī)間。然後将距離乘以(yǐ)一個(gè)系數,作爲(wéi / wèi)長按時(shí)間并模拟執行即可。
運行結果
看起來(lái)很不(bù)錯,實際跑分結果如何呢?
大(dà)概隻能達到(dào)幾百分,問題出(chū)在(zài)哪?
主要(yào / yāo)是(shì)标注數據太少,模型訓練得不(bù)夠充分,所以(yǐ)檢測結果不(bù)夠準确,有時(shí)候檢測不(bù)出(chū)棋子(zǐ)和(hé / huò)目标塊,而(ér)一旦出(chū)現這(zhè)類問題,分數必然就(jiù)斷了(le/liǎo)。
嘗試了(le/liǎo)以(yǐ)下方法,将一張截圖朝不(bù)同的(de)方向平移,從而(ér)得到(dào)九張截圖,希望提高檢測結果的(de)召回率,但仍然有檢測不(bù)出(chū)來(lái)的(de)情況,也(yě)許隻有靠更多的(de)标注數據才能解決這(zhè)一問題。
規則檢測
模型訓練了(le/liǎo)20W輪,依舊存在(zài)檢測不(bù)出(chū)來(lái)的(de)情況,郁悶得很,幹脆也(yě)寫一個(gè)基于(yú)規則的(de) 簡單版代碼 好了(le/liǎo)。
花了(le/liǎo)不(bù)到(dào)20分鍾寫完代碼,用OpenCV
提取邊緣,然後檢測棋子(zǐ)和(hé / huò)目标塊的(de)水平中心位置,結果看起來(lái)像這(zhè)樣。
事實證明,最後跑出(chū)來(lái)的(de)分數,比之(zhī)前的(de)模型要(yào / yāo)高多了(le/liǎo)……
說(shuō)好的(de)深度學習呢?
總結
面對以(yǐ)下情況時(shí),基于(yú)人(rén)工經驗定義規則,比用深度學習訓練模型要(yào / yāo)省力、有效很多:
- 問題本身比較簡單,不(bù)需要(yào / yāo)複雜的(de)抽象;
- 标注數據比較有限,難以(yǐ)充分訓練模型;
- 錯誤懲罰很高,對錯誤不(bù)能容忍。即便模型在(zài)99%的(de)情況下能完美運行,1%的(de)錯誤立馬讓遊戲直接結束了(le/liǎo),此時(shí)反而(ér)不(bù)如hard code的(de)規則靠譜。
當然,如果大(dà)家能一起努力,多弄些标注數據出(chū)來(lái),說(shuō)不(bù)定還有些希望。
代碼在(zài)Github上(shàng):github.com/Honlan/wech…
不(bù)說(shuō)了(le/liǎo),我繼續刷分去了(le/liǎo),用後面寫的(de)不(bù)到(dào)一百行的(de)代碼……