AI 玩跳一跳的正確姿勢,跳一跳 Auto-Jump 算法詳解

2021-02-07 Python開發者

(點擊上方藍字,快速關注我們)


來源:肖泰洪 + 安捷 

zhuanlan.zhihu.com/p/32636329


最近,微信小遊戲跳一跳可以說是火遍了全國,從小孩子到大孩子仿佛每一個人都在刷跳一跳,作為無(zhi)所(hui)不(ban)能(zhuan)的AI程式設計師,我們在想,能不能用人工智慧(AI)和計算機視覺(CV)的方法來玩一玩這個遊戲?於是,我們開發了微信跳一跳Auto-Jump算法,重新定義了玩跳一跳的正確姿勢,我們的算法不僅遠遠超越了人類的水平,在速度和準確度上也遠遠超越了目前已知的所有算法,可以說是跳一跳界的state-of-the-art,下面我們詳細介紹我們的算法。

算法的第一步是獲取手機屏幕的截圖並可以控制手機的觸控操作,我們的github倉庫裡詳細介紹了針對Android和IOS手機的配置方法。

你只需要按照將手機連接電腦,按照教程執行就可以完成配置。在獲取到屏幕截圖之後,就是個簡單的視覺問題。我們需要找的就是小人的位置和下一次需要跳的臺面的中心。

如圖所示,綠色的點代表小人當前的位置,紅點代表目標位置。

多尺度搜索(Multiscale Search)

這個問題可以有非常多的方法去解,為了糙快猛地刷上榜,我一開始用的方式是多尺度搜索。我隨便找了一張圖,把小人摳出來,就像下面這樣。

另外,我注意到小人在屏幕的不同位置,大小略有不同,所以我設計了多尺度的搜索,用不同大小的進行匹配,最後選取置信度(confidence score)最高的。

多尺度搜索的代碼長這樣

def multi_scale_search(pivot, screen, range=0.3, num=10):

    H, W = screen.shape[:2]

    h, w = pivot.shape[:2]

 

    found = None

    for scale in np.linspace(1-range, 1+range, num)[::-1]:

        resized = cv2.resize(screen, (int(W * scale), int(H * scale)))

        r = W / float(resized.shape[1])

        if resized.shape[0] < h or resized.shape[1] < w:

            break

        res = cv2.matchTemplate(resized, pivot, cv2.TM_CCOEFF_NORMED)

 

        loc = np.where(res >= res.max())

        pos_h, pos_w = list(zip(*loc))[0]

 

        if found is None or res.max() > found[-1]:

            found = (pos_h, pos_w, r, res.max())

 

    if found is None: return (0,0,0,0,0)

    pos_h, pos_w, r, score = found

    start_h, start_w = int(pos_h * r), int(pos_w * r)

    end_h, end_w = int((pos_h + h) * r), int((pos_w + w) * r)

    return [start_h, start_w, end_h, end_w, score]


我們來試一試,效果還不錯,應該說是又快又好,我所有的實驗中找小人從來沒有失誤。

不過這裡的位置框的底部中心並不是小人的位置,真實的位置是在那之上一些。

同理,目標臺面也可以用這種辦法搜索,但是我們需要收集一些不同的臺面,有圓形的,方形的,便利店,井蓋,稜柱等等。由於數量一多,加上多尺度的原因,速度上會慢下來。這時候,我們就需要想辦法加速了。首先可以注意到目標位置始終在小人的位置的上面,所以可以操作的一點就是在找到小人位置之後把小人位置以下的部分都捨棄掉,這樣可以減少搜索空間。但是這還是不夠,我們需要進一步去挖掘遊戲裡的故事。小人和目標臺面基本上是關於屏幕中心對稱的位置的。這提供了一個非常好的思路去縮小搜索空間。假設屏幕解析度是(1280,720)的,小人底部的位置是(h1, w1),那麼關於中心對稱點的位置就是(1280 – h1, 720 – w1),以這個點為中心的一個邊長300的正方形內,我們再去多尺度搜索目標位置,就會又快有準了。效果見下圖,藍色框是(300,300)的搜索區域,紅色框是搜到的臺面,矩形中心就是目標點的坐標了。

加速的奇技淫巧(Fast-Search)

玩遊戲需要細心觀察。我們可以發現,小人上一次如果跳到臺面中心,那麼下一次目標臺面的中心會有一個白點,就像剛才所展示的圖裡的。更加細心的人會發現,白點的RGB值是(245,245,245),這就讓我找到了一個非常簡單並且高效的方式,就是直接去搜索這個白點,注意到白點是一個連通區域,像素值為(245,245,245)的像素個數穩定在280-310之間,所以我們可以利用這個去直接找到目標的位置。這種方式只在前一次跳到中心的時候可以用,不過沒有關係,我們每次都可以試一試這個不花時間的方法,不行再考慮多尺度搜索。

講到這裡,我們的方法已經可以運行的非常出色了,基本上是一個永動機。下面是用我的手機玩了一個半小時左右,跳了859次的狀態,我們的方法正確的計算出來了小人的位置和目標位置,不過我選擇狗帶了,因為手機卡的已經不行了。

以下是效果演示:



這裡有一個示例視頻,歡迎觀看!

視頻連結:https://v.vzuu.com/video/932359600779309056


到這裡就結束了嗎?那我們和業餘玩家有什麼區別?下面進入正經的學術時間,非戰鬥人員請迅速撤離!

CNN Coarse-to-Fine 模型

考慮到IOS設備由於屏幕抓取方案的限制(WebDriverAgent獲得的截圖經過了壓縮,圖像像素受損,不再是原來的像素值,原因不詳,歡迎了解詳情的小夥伴提出改進意見~)無法使用fast-search,同時為了兼容多解析度設備,我們使用卷積神經網絡構建了一個更快更魯棒的目標檢測模型,下面分數據採集與預處理,coarse模型,fine模型,cascade四部分介紹我們的算法。

數據採集與預處理

基於我們非常準確的multiscale-search、fast-search模型,我們採集了7次實驗數據,共計大約3000張屏幕截圖,每一張截圖均帶有目標位置標註,對於每一張圖,我們進行了兩種不同的預處理方式,並分別用於訓練coarse模型和fine模型,下面分別介紹兩種不同的預處理方式。

Coarse 模型數據預處理

由於每一張圖像中真正對於當前判斷有意義的區域只在屏幕中央位置,即人和目標物體所在的位置,因此,每一張截圖的上下兩部分都是沒有意義的,因此,我們將採集到的大小為1280*720的圖像沿x方向上下各截去320*720大小,只保留中心640*720的圖像作為訓練數據。

我們觀察到,遊戲中,每一次當小人落在目標物中心位置時,下一個目標物的中心會出現一個白色的圓點,

考慮到訓練數據中fast-search會產生大量有白點的數據,為了杜絕白色圓點對網絡訓練的幹擾,我們對每一張圖進行了去白點操作,具體做法是,用白點周圍的純色像素填充白點區域。

Fine 模型數據預處理

為了進一步提升模型的精度,我們為fine模型建立了數據集,對訓練集中的每一張圖,在目標點附近截取320*320大小的一塊作為訓練數據,

為了防止網絡學到trivial的結果,我們對每一張圖增加了50像素的隨機偏移。fine模型數據同樣進行了去白點操作。

Coarse 模型

我們把這一問題看成了回歸問題,coarse模型使用一個卷積神經網絡回歸目標的位置,

def forward(self, img, is_training, keep_prob, name='coarse'):

    with tf.name_scope(name):

        with tf.variable_scope(name):

            out = self.conv2d('conv1', img, [3, 3, self.input_channle, 16], 2)

            # out = tf.layers.batch_normalization(out, name='bn1', training=is_training)

            out = tf.nn.relu(out, name='relu1')

 

            out = self.make_conv_bn_relu('conv2', out, [3, 3, 16, 32], 1, is_training)

            out = tf.nn.max_pool(out, [1, 2, 2, 1], [1, 2, 2, 1], padding='SAME')

 

            out = self.make_conv_bn_relu('conv3', out, [5, 5, 32, 64], 1, is_training)

            out = tf.nn.max_pool(out, [1, 2, 2, 1], [1, 2, 2, 1], padding='SAME')

 

            out = self.make_conv_bn_relu('conv4', out, [7, 7, 64, 128], 1, is_training)

            out = tf.nn.max_pool(out, [1, 2, 2, 1], [1, 2, 2, 1], padding='SAME')

 

            out = self.make_conv_bn_relu('conv5', out, [9, 9, 128, 256], 1, is_training)

            out = tf.nn.max_pool(out, [1, 2, 2, 1], [1, 2, 2, 1], padding='SAME')

 

            out = tf.reshape(out, [-1, 256 * 20 * 23])

            out = self.make_fc('fc1', out, [256 * 20 * 23, 256], keep_prob)

            out = self.make_fc('fc2', out, [256, 2], keep_prob)

 

    return out


經過十小時的訓練,coarse模型在測試集上達到了6像素的精度,實際測試精度大約為10像素,在測試機器(MacBook Pro Retina, 15-inch, Mid 2015, 2.2 GHz Intel Core i7)上inference時間0.4秒。這一模型可以很輕鬆的拿到超過1k的分數,這已經遠遠超過了人類水平和絕大多數自動算法的水平,日常娛樂完全夠用,不過,你認為我們就此為止那就大錯特錯了~

Fine 模型

fine模型結構與coarse模型類似,參數量稍大,fine模型作為對coarse模型的refine操作,

def forward(self, img, is_training, keep_prob, name='fine'):

    with tf.name_scope(name):

        with tf.variable_scope(name):

            out = self.conv2d('conv1', img, [3, 3, self.input_channle, 16], 2)

            # out = tf.layers.batch_normalization(out, name='bn1', training=is_training)

            out = tf.nn.relu(out, name='relu1')

 

            out = self.make_conv_bn_relu('conv2', out, [3, 3, 16, 64], 1, is_training)

            out = tf.nn.max_pool(out, [1, 2, 2, 1], [1, 2, 2, 1], padding='SAME')

 

            out = self.make_conv_bn_relu('conv3', out, [5, 5, 64, 128], 1, is_training)

            out = tf.nn.max_pool(out, [1, 2, 2, 1], [1, 2, 2, 1], padding='SAME')

 

            out = self.make_conv_bn_relu('conv4', out, [7, 7, 128, 256], 1, is_training)

            out = tf.nn.max_pool(out, [1, 2, 2, 1], [1, 2, 2, 1], padding='SAME')

 

            out = self.make_conv_bn_relu('conv5', out, [9, 9, 256, 512], 1, is_training)

            out = tf.nn.max_pool(out, [1, 2, 2, 1], [1, 2, 2, 1], padding='SAME')

 

            out = tf.reshape(out, [-1, 512 * 10 * 10])

            out = self.make_fc('fc1', out, [512 * 10 * 10, 512], keep_prob)

            out = self.make_fc('fc2', out, [512, 2], keep_prob)

 

    return out


經過十小時訓練,fine模型測試集精度達到了0.5像素,實際測試精度大約為1像素,在測試機器上的inference時間0.2秒。

Cascade

總體精度1像素左右,時間0.6秒。

總結

針對這一問題,我們利用AI和CV技術,提出了合適適用於IOS和Android設備的完整解決方案,稍有技術背景的用戶都可以實現成功配置、運行,我們提出了Multiscale-Search,Fast-Search,CNN Coarse-to-Fine三種解決這一問題的算法,三種算法相互配合,可以實現快速準確的搜索、跳躍,用戶針對自己的設備稍加調整跳躍參數即可接近實現「永動機」。講到這裡,似乎可以宣布,我們的工作terminate了這個問題,微信小遊戲跳一跳game over!

友情提示:適度遊戲益腦,沉迷遊戲傷身,技術手段的樂趣在於技術本身而不在遊戲排名,希望大家理性對待遊戲排名和本文提出的技術,用遊戲娛樂自己的生活

聲明:本文提出的算法及開原始碼符合MIT開源協議,以商業目的使用該算法造成的一切後果須由使用者本人承擔

Git倉庫地址:

https://github.com/Prinsphield/Wechat_AutoJump

https://github.com/Richard-An/Wechat_AutoJump


看完本文有收穫?請轉發分享給更多人

關注「Python開發者」,提升Python技能

相關焦點

  • AI 玩跳一跳的正確姿勢,Auto-Jump 算法詳解
    ,從小孩子到大孩子仿佛每一個人都在刷跳一跳,作為無(zhi)所(hui)不(ban)能(zhuan)的AI程式設計師,我們在想,能不能用人工智慧(AI)和計算機視覺(CV)的方法來玩一玩這個遊戲?於是,我們開發了微信跳一跳Auto-Jump算法,重新定義了玩跳一跳的正確姿勢,我們的算法不僅遠遠超越了人類的水平,在速度和準確度上也遠遠超越了目前已知的所有算法,可以說是跳一跳界的state-of-the-art,下面我們詳細介紹我們的算法。
  • 教程 | AI玩微信跳一跳的正確姿勢:跳一跳Auto-Jump算法詳解
    最近,微信小遊戲跳一跳可以說是火遍了全國,從小孩子到大孩子仿佛每一個人都在刷跳一跳,作為無(zhi)所(hui)不(ban)能(zhuan)的
  • Python程序突破微信小遊戲」跳一跳「
    微信2017年12月28日發布了新版本,在小程序裡面有一個跳一跳小遊戲,一下子引爆了微信朋友圈,大家紛紛加入跳一跳PK。
  • 微信跳一跳輔助軟體在哪裡下載?跳一跳輔助軟體怎麼改分數教程一覽
    微信跳一跳輔助軟體網上有很多,不外乎下面這幾種。那麼這個微信跳一跳輔助軟體該怎麼用呢?改分向(謹慎使用)1、首先下一個Packet Capture安裝。3、再打開你的微信,進入跳一跳,隨便玩下。4、返回到Packet Capture,查看記錄的事件,找到帶有「SSL」字樣的微信記錄欄位。
  • 想成為微信跳一跳之神嗎 AI算法來幫你
    最近,微信小遊戲跳一跳可以說是火遍了全國,從小孩子到大孩子仿佛每一個人都在刷跳一跳,作為無(zhi)所(hui)不(ban)能(zhuan)的
  • 王者逆襲:教你用人工智慧玩微信跳一跳,高分逆襲!
    最近,微信小遊戲跳一跳可以說是火遍了全國,從小孩子到大孩子仿佛每一個人都在刷跳一跳
  • 當你還在玩微信「跳一跳」, 小心跳出這種病!
    近日,「跳一跳」小遊戲風靡朋友圈,很多盆友好奇地點開嘗試。最後發現跳到根本停不下來。每當看到遊戲排名榜就會引發心底那點較勁的念頭,於是控制不住寄己啊,又在跳啊跳。當你還在瘋狂地玩微信「跳一跳」,腱鞘炎關節痛已經慢慢找上門了!今天就跟大家說一說關於腱鞘炎的那些事兒。
  • 微信「跳一跳」:玩的是小遊戲,悟的是大道理!
    「跳一跳」,深受用戶喜愛。03「跳一跳」的玩法很簡單,每個人接觸的時候,都會覺得自己可以輕易拿到高分。然而只要上手,就會迅速感到挫敗,哪怕拿10分都非常困難。由於自我的驕傲,我們根本無法接受這個事實,為了不斷挑戰自己,就會樂此不疲地跳下去。
  • 微信跳一跳小遊戲怎麼玩?從哪裡進入呢?
    微信推送6.6.1版本更新後,上線了一款全新的微笑跳一跳小遊戲,而且現在朋友圈玩瘋了,而且很多用戶還不知道跳一跳這款遊戲是怎樣的一款遊戲,甚至都不知道從哪進
  • 眼皮在 「跳」 英文怎麼說?可不是jump!
    ↑ ↑ ↑ ↑ ↑ ↑ ↑ 新朋友,請先關注,再領福利~申請的人很多,但我們會儘快為你安排課程, 保持手機暢通,耐心等待小編覺得,什麼時候能實現暴富都靠這雙眼睛了不都說 「左眼跳災,右眼跳財」 嘛(其實純粹是沒睡好)那,說自己眼皮跳的厲害這個跳可不是jump
  • 微信跳一跳裝逼輔助
    2018年最火的小遊戲就是微信小程序推出來的跳一跳了,大多數都是跳了兩三百分的,據說最高分是2019分,加2步妥妥的,之需要用這款微信跳一跳輔助
  • 微信跳一跳
    微信跳一跳 步驟實現如下~1、用安卓手機安裝我發送的apk包 2、下載好之後點擊進入到「遊戲蜂窩」app的主頁面
  • 從前有一個人熬夜玩「跳一跳」,後來他死了
    我最討厭這類遊戲我才不願意跟我玩不好的遊戲瞎較勁好了故事結束了聽我講完你會不會覺得「跳一跳」沒用外掛的那些人到底是怎樣一種力量激發出他們如此可怕的潛能呢一位姑娘說把跳一跳從重來一局就好了但愛情呢沒有重來最後,關於怎麼把「跳一跳
  • 微信跳一跳外掛改分詳細教程 微信跳一跳作弊腳本源碼分享
    近期,有不少小夥伴都被微信朋友圈的跳一跳遊戲的衝分排行榜給刷屏,而大家也都為跳一跳衝分而樂此不疲【附:微信跳一跳技巧大全】,但是有人發現排行榜中出現了一些近乎不可能的分數,那微信跳一跳遊戲怎麼改分?下面為大家帶來跳一跳改分教程及腳本源碼。
  • 蘋果iPhone手機怎麼修改微信跳一跳分數 ios系統作弊改分教程
    微信最近有個跳一跳的小遊戲超級好玩呀,小編是玩了很久都沒有得過高分,不過好像可以改分耶,下面小編分享一下ios系統的改分方法哦~  微信跳一跳ios怎麼改分 蘋果系統改分教程詳解  蘋果手機抓包sesseion_id:  1、mac下選用charles作為抓包代理軟體
  • 讓全武漢的「跳一跳」愛好者集結起來
    公司有個小姑娘,每次打到一個特定的分數就不跳了,她說:「近期我和他距離最近的時刻,就是在跳一跳排行榜上挨在一起的時候。」「跳一跳」火是真的,也大把的消耗了我的時間,打開手機往那一坐就是幾個小時,下班回家的地鐵上咚咚咚,吃飯咚咚咚,甚至睡覺都要咚咚咚。
  • 「跳一跳」這遊戲有毒...| 「有毒」英語怎麼表達?
    I tried out Tiao Yi Tiao, a simple but gripping game in which the length of your press on the character dictates how far you jump.
  • 微信「跳一跳」小技巧
    最近看微信好友都在玩「跳一跳」,還在朋友圈裡面曬分數。跟風玩兒了兩天,剛開始只能得到幾十分,不過後來發現了一些規律,平均分基本上在 200 左右,這裡和大家分享一下這些規律:1、如果連續跳到落腳物品的中間點分數會有加成,有點類似於「連擊」,如果你能夠連續五六次都落在中點,跳一次都能得到十幾分,是不是很爽?2、在汙水井蓋兒上停留一會兒,會聽到衝水的聲音,分數會增加 5。
  • 曝:微信「跳一跳」遊戲外掛,神操作...
    你們玩了微信遊戲「跳一跳」嗎?這個遊戲有毒,只要無聊的時候,就忍不住想玩玩它。
  • 健康一課|跳一跳遊戲的通關秘籍在此!
    這款流行的小遊戲「微信之父」張小龍都在玩,您呢?