[Mediapipe] Hands 操作實戰:用手勢操控電腦(下)
本篇記錄運行 Mediapipe 成果的小筆記。
Reference: Google 官方MediaPipe說明文件
Slides:
Project Demo影片:
那麼就開始介紹吧。
一、環境建置
首先,要先有python運行環境,這部分有相當多的人介紹,可以尋找適合自己的IDE,進行開發與測試。
安裝套件
主要需要的套件如題所述,要有mediapipe。
(OpenCV, numpy, Pandas, matplotlib, Keras, scikit-learn等依需求安裝。)
# 於cmd或已建立環境中,安裝套件
pip install mediapipe# 於開發環境導入套件
import mediapipe as mp
產出概覽
這篇文章只會提到概要的內容,如果對完整資訊有興趣可以到github上。
主程式是 app_3000.py,模型檔見 model資料夾 內容。
最終建立Model的hdf5與tflite檔(後者適合放入嵌入式裝置,例如樹莓派RaspberryPi),結合執行檔,進行手勢判斷。
其後可以疊加的功能就相當豐富了,主要可以透過PyAuto、PyAutoGUI(後者比較新,且相對有持續更新) 來操控滑鼠、鍵盤,或是再進一步開發到硬體裝置上,讓其應用更加廣泛。
功能參考如Microsoft Research的Project Prague — Demos
透過手勢操控電腦,可以選轉角度、放大縮小、抓取物件等等。
或是以Youtube平台本身有許多快捷鍵,只要將手勢結合到快捷鍵操控,就可以實踐手勢YT控制器。
二、透過Hands擷取資料。
我們將根據這些資料進行應用開發。
- max_num_hands為手的最大偵測數量,1為最多偵測1隻手,2是2隻手,先進畫面先辨識。
- min_detection_confidence 直接帶入default 為
0.5
。 - min_tracking_confidence 直接帶入default 為
0.5
。
# 進行手部資料辨識,並抓取手的20個點資料
mp_hands = mp.solutions.hands
hands = mp_hands.Hands(
static_image_mode=use_static_image_mode,
max_num_hands=1,
min_detection_confidence=min_detection_confidence,
min_tracking_confidence=min_tracking_confidence,
)
資料撈出後,就是鏡頭畫面、資料存取與進行訓練的功夫了。
三、鏡頭畫面
以一個基本的畫面擷取來說,當我們要用筆電鏡頭來做為資料input,可以透過OpenCV的函式來達成,當然也需要計算fps,來判斷目前硬體運行的效率。
特別注意VideoCapture(),帶入不同參數代表的意義。
- 0 : 默認為筆記本上的攝像頭(如果有的話) / USB攝像頭 webcam
- 1 : USB攝像頭1
- 2 :USB攝像頭2,依此類推。
- -1:代表最新插入的USB設備cap = cv2.VideoCapture(0)
import cv2
import time
import oswCam, hCam = 640, 480# 注意VideoCapture的裝置編號
cap = cv2.VideoCapture(0)
cap.set(3, wCam)
cap.set(4, hCam)# 建立計算fps機制
pTime = 0
while True:
success, img = cap.read()
cTime = time.time()
fps = 1 / (cTime — pTime)
pTime = cTimecv2.putText(img, f’FPS: {int(fps)}’, (400, 70), cv2.FONT_HERSHEY_PLAIN, 3, (255, 0, 0), 3)
cv2.imshow(“Image”, img)
# 按 q 離開應用(app)
if cv2.waitKey(1) & 0xFF == ord(‘q’):
break
四、資料存取
存取資料的方式有許多種,但以Hands可以取得資料在上一篇介紹中,我們可以得知資料是依據左右手、每隻手21個landmarks進行資料存取。
但是為什麼要判斷 if __ is not None,且要拆成兩種資料進行變數存取呢 ?
Landmarks
以實際查看mediapipe給我們results來說,results.multi_hand_landmarks的資料結構如上,並沒有根據landmark進行標號,但我們可以透過資料排序知道每一個landmark代表的是哪一個關節點。
而資料是已經經過標準化後的結果,包含水平(X)、垂直(Y)以及景深(Z)座標,這些座標點會根據手腕點(編號=0 landmark)進行變化。
設計為while迴圈持續取值,直到None,就是加在判斷式進行的,照順序取也可以如上一回提到的官方文件說明來存取每隻手21個landmarks座標點:
再來就是results.multi_handedness了,mediapipe存了什麼?
意思是感應當前的手,是左手 或 右手,為mediapipe本身就寫好的功能,辨識度相當高,但實際體驗有當手在相對左邊,就是左手,反之亦然的感覺。
五、進行訓練
訓練前最重要的就是,定義手勢(Y, label),確定手勢。
我們可以根據需求,設計出不同的手勢,並透過鏡頭畫面,結合資料存取,將當前比出的手勢座標點(landmarks)存下,並給予label。
以前面提到的Youtube手勢功能,我們就可以做出不同的手勢進行模型訓練,基本上不需要用到太複雜模型,因為已經是點座標,透過幾層的類神經網絡模型(NN model)就可以達到相當好的結果。
其他小事:模型train爛怎麼辦?
- 訓練模型要特別回測手勢,是否正常使用的角度資料都能好好辨識。
- 若有辨識不好的問題怎麼處理?
1. 補未能好好辨識的手勢資料。2. 不要用這個手勢。
- 增加即時模型辨識穩定度,可以設計根據多個frame(畫面)取最常出現的手勢進行功能操作。
訓練完,透過tflite的輕量化模型轉換,結合OpenCV抓取鏡頭資訊,就可以透過訓練好的model進行即時手勢偵測,並拿來應用。
結語
執行這份專案到有小成果時,大概需要注意以上這幾點,再來就是操作的手感與如何進行操控的設計了。
目前是覺得滑鼠最實用,鍵盤感覺有點難…,因為要搭配的手勢多樣,除非有特別難按或真的適用的情境,否則意義不明。
文章到結尾了,感謝你/妳的收看 ^^