[Mediapipe] Hands 操作實戰:用手勢操控電腦(下)

ChunJen Wang
jimmy-wang
Published in
8 min readMay 27, 2021

本篇記錄運行 Mediapipe 成果的小筆記。

Reference: Google 官方MediaPipe說明文件

Source: Google MediaPipe Github.io

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),結合執行檔,進行手勢判斷。

Model 手勢判斷列表,可透過資料訓練自定義

其後可以疊加的功能就相當豐富了,主要可以透過PyAutoPyAutoGUI(後者比較新,且相對有持續更新) 來操控滑鼠、鍵盤,或是再進一步開發到硬體裝置上,讓其應用更加廣泛。

功能參考如Microsoft Research的Project Prague — Demos

透過手勢操控電腦,可以選轉角度、放大縮小、抓取物件等等。

或是以Youtube平台本身有許多快捷鍵,只要將手勢結合到快捷鍵操控,就可以實踐手勢YT控制器。

『 YouTube快捷鍵 』不會用就落伍了!別再傻傻點齒輪啦!Source: 電獺少女編輯屋

二、透過Hands擷取資料。

如同上篇介紹,每一隻手會有21個landmarks

我們將根據這些資料進行應用開發。

  • 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 os
wCam, 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 = cTime
cv2.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)就可以達到相當好的結果。

Model Performance (confusion matrix)

其他小事:模型train爛怎麼辦?

  • 訓練模型要特別回測手勢,是否正常使用的角度資料都能好好辨識。
  • 若有辨識不好的問題怎麼處理?
    1. 補未能好好辨識的手勢資料。2. 不要用這個手勢。
  • 增加即時模型辨識穩定度,可以設計根據多個frame(畫面)取最常出現的手勢進行功能操作。
抓手勢為id=4(此為動態)進行操控。

訓練完,透過tflite的輕量化模型轉換,結合OpenCV抓取鏡頭資訊,就可以透過訓練好的model進行即時手勢偵測,並拿來應用。

結語

執行這份專案到有小成果時,大概需要注意以上這幾點,再來就是操作的手感與如何進行操控的設計了。

目前是覺得滑鼠最實用,鍵盤感覺有點難…,因為要搭配的手勢多樣,除非有特別難按或真的適用的情境,否則意義不明。

文章到結尾了,感謝你/妳的收看 ^^

--

--

ChunJen Wang
jimmy-wang

嗨,歡迎你的到來,我目前在銀行擔任DS。過去曾做過銀行大型專案BA,也曾在轉職科技業DE中踢了鐵板,相信每一個人都有自己要走的路,而努力的過程,可以讓我們離心中理想更接近,如果我的文章能帶給你一些啟發與幫助,別忘了幫我在文章底下按下拍手~^^