Python跳一跳之樹莓派純硬體實現

項目源碼:DaddyGang/WeChat_JumpMaster

主要參考:

皮皮哇:Python玩「跳一跳」 iOS+Win 硬體實現?

zhuanlan.zhihu.com圖標

感謝 @皮皮哇

細數跳一跳外掛

雖然現在跳一跳已經熱度不在,但是這款遊戲單一的操作,簡潔的元素化的界面,實在是一個對於外掛製作者不可多得的良品。網路上各式的或軟或硬的外掛已經琳琅滿目,我在這裡也算是做個總結吧。

  • 人工識別 軟體派

神奇的戰士:教你用Python來玩微信跳一跳

跳一跳外掛界的開山鼻祖,利用安卓機和adb工具手動描點計算距離,後期已經更新自動識別代碼。

  • 人工識別 硬體派

李帥:跳一跳 簡易物理外掛(非圖像處理)

這位大神利用正點原子的STM32開發板+攝像頭+舵機+火腿腸和他的眼睛完成了任務。

  • 自動識別+軟體派

微信小遊戲跳一跳外掛教程(安卓版)

船D長:用Python+Opencv讓電腦幫你玩微信跳一跳

對於使用USB調試的方法,只適用於安卓機。如果你是IOS,那麼你需要Mac的WDA工具,原理同adb工具,如果沒有,這個方法就gg了。

  • 自動識別+硬體派

Python玩「跳一跳」 iOS+Win 硬體實現

自動玩微信「跳一跳」之純物理實現

這一派接近嵌入式的最高境界,可惜依然需要電腦輔助運算。

所有軟體方案由於目前都會被判定為可疑行為,不會在排行榜顯示,而硬體舵機的方案由於每次按壓都存在輕微的震動,所以不會被判定為作弊。

硬體外掛的最終形態

樹莓派連接Raspicam+S90舵機,所有運算在樹莓派上完成。

https://www.zhihu.com/video/967389579377057792

系統的基本框架:

  1. python調用picamera庫,採集到的圖像預處理後轉化成opencv數據格式
  2. opencv分析圖像,計算出距離,乘以時間係數得到按壓時間
  3. 調用GPIO口,執行按壓操作

前期準備

  1. 硬紙板若干,塑料泡沫若干,電容筆,杜邦線,一個橘子
  2. 樹莓派3B,樹莓派原裝攝像頭,9g舵機
  3. python包:python-opencv,picamera,numpy
  4. 調試環境:搭建sftp用於查看計算後的圖片輸出,顯示器用於調整攝像頭位置(可選)

硬體搭建

  • 用膠槍把電容筆固定到舵機擺臂上,放置在合適的高度(我用的是一個含片的盒子),杜邦線減去一頭,剝出銅線,固定在電容筆的金屬部分,另一頭插入多汁水果

  • SG90舵機紅線接5V電源,棕線GND,黃線接GPIO18

  • 剪一長條形的硬紙板,中間開孔,讓攝像頭通過

  • 將攝像頭插上樹莓派,沿硬紙板水平伸出,樹莓派用泡沫墊高約11到12cm

  • 效果圖

軟體與調試環境搭建

  • 安裝Raspbian系統,更換鏡像源,串口或者SSH連接樹莓派,我安裝的是Raspbian GUN/Linux 9.4 (stretch),很遺憾浙大鏡像站上沒有對應9代的鏡像源, 推薦 清華大學開源鏡像站。

pi@raspberrypi ~ $ sudo nano /etc/apt/sources.list

  • 更新並安裝pip,picamera

//更新軟體pi@raspberrypi ~ $ sudo apt-get update pi@raspberrypi ~ $ sudo apt-get upgrade//安裝pippi@raspberrypi ~ $ sudo apt-get install python-pippi@raspberrypi ~ $ sudo pip install picamera

  • 固定你的pi區域網IP,安裝vsftp,並開啟服務

  • 連接並打開攝像頭,注意引腳面朝乙太網口

pi@raspberrypi ~ $ sudo raspi-config

9代stretch系統的攝像頭配置業被隱藏到了Interfacing Options選項卡中,注意!

選擇Enable

  • 安裝opencv,只要兩條語句

pi@raspberrypi ~ $ sudo apt-get install libopencv-dev pi@raspberrypi ~ $ sudo apt-get install python-opencv

此處說明:這種方法只能用於python2.7,想用python3的同學請乖乖編譯cv源碼

  • 一切搞定後的測試

測試代碼:運行後會在10秒預覽後拍照存入根目錄,可以通過flashfxp登陸樹莓派查看

# -*- coding: utf-8 -*- import timeimport picameraimport picamera.arrayimport cv2up_B, down_B, left_B, right_B = 0,768,0,1024 #裁剪原始圖像的邊界with picamera.PiCamera() as camera: camera.resolution = (1024, 768) camera.vflip = True #攝像頭倒置,所以要作垂直翻轉 camera.start_preview() time.sleep(10) with picamera.array.PiRGBArray(camera) as stream: camera.capture(stream, format=bgr) # 此時就可以獲取到bgr的數據流了 image = stream.array image = image[up_B:down_B, left_B:right_B] cv2.imwrite("image.jpg",image)

參數校準

首先通過sftp將源代碼目錄下的py文件和png圖片文件傳到樹莓派根目錄,分別執行測試

  • 舵機位置的校準

pi@raspberrypi ~ $ python servo.py

運行servo.py,改變up和down兩個參數(在2.5到12.5之間,對應0°和180°),使得在down時電容筆按下,up時離開,也可以去掉注釋,在循環中找到舵機的最佳臨界位置。

  • 照片素材的裁剪

pi@raspberrypi ~ $ python cap.py

手機調亮度最大,在攝像頭下就位運行cap.py,電腦端查看得到的image文件的長寬像素比,用畫圖軟體找到手機屏幕上下左右邊界的像素坐標,分別對應up_B, down_B, left_B, right_B四個參數。(坐標選擇的原則是寧願多割掉一點也不要留邊)修改參數,再次運行,查看效果:

  • 識別效果調整

pi@raspberrypi ~ $ python reco_pi.py

運行recopi.py, 根據效果圖,改變參數表中的參數

由於樹莓派攝像頭很垃圾,在邊緣檢測前做圖像預處理還是很有必要的,查看c2.png可以看出調節低通濾波參數的效果

高斯矩陣(3,3)標準差0 高斯矩陣(5,5)標準差3

最終識別的效果

原圖 標記

最後把整定好的參數代入到beta_test.py中,在樹莓派上運行,找到適合的按壓時間係數

一切準備就緒之後就可以開始運行了。

OpenCV演算法簡析

  • 演算法部分基本沿用了@皮皮哇分享的源碼。
  • 基本的思路就是把要素摳出來,和拍到的圖像做模板匹配,特殊加分目標和小圓點的匹配效果並不好。小圓點應該是由於目標太小了,像素的微擾就會使得匹配度大打折扣。而加分目標的匹配效果不好的原因應該是絕大部分目標的形狀和普通板並沒有大區別,其內部的差異對匹配度的影響並不大。
  • 我在大神的基礎上,增加了基於模板輪廓圖像的匹配,稍稍提高了成功率
  • 值得說明的是,樹莓派計算速度較慢,每次等待的時間都足以讓人不錯過加分項

總結

  • 自動識別已經有相當高的準確度,模板匹配的問題預計需要引入機器學習來解決
  • 硬體實現中舵機,攝像頭等硬體引入的誤差使得它比軟體實現要不穩定多

最後祭上千分大作

https://www.zhihu.com/video/967425035971104768


來自某人的嵌入式大作業,第一次發文章,在跳一跳的遲暮之年,但求路過看官留贊。

推薦閱讀:

python如何理解map,reduce,filter?
有什麼好的django開源項目值得參考?
Python 北京開發者活動第一期視頻放出!
已經有了各省的數據,如何將信息以可視化的方式顯示在地圖上?順便問一下python有相關的第三方包沒?
基於bs4庫的HTML內容查找方法

TAG:Python | 樹莓派RaspberryPi | 跳一跳 |