帳號:
密碼:
最新動態
產業快訊
CTIMES / 文章 /
Google MediaPipe快速上手 ─ 浮空手勢也能用來當作簡報播放器
【vMaker Edge AI專欄 #05】

【作者: Jack OmniXRI】   2023年05月29日 星期一

瀏覽人次:【4457】

2019年6月時Google在電腦視覺頂級研討會CVPR上展示了MediaPipe[1]的預覽版本,提出了可供移動裝置運行手部追蹤、人臉追蹤及物體偵測等功能的輕量模型開源程式。這項工具不僅可在Android, iOS, Web, Windows等平台上運行,亦支援如C++, Python, JavaScript等程式語言開發。由於它非常輕量,所以可輕鬆佈署在像樹莓派、Nvidia Jetson Nano等小型單板微電腦上,非常適合想學習AI應用的新手朋友。


接下來我們就簡單幫大家認識一下MediaPipe及其手部追蹤、手部特徵點提取及手勢辨識的原理,最後再用一個浮空手勢辨識來控制PowerPoint簡報播放的實例,讓大家可以感受一下這項方便的工具神奇好用之處。


1. MediaPipe簡介及開發環境建置

MediaPipe歷經數年的改善,增減了許多功能,原本官方網站[2]是依附在其Github[3]下,但2023/4/3後已正式獨立出來了[1]。新版停止支持一些不常用的電腦視覺功能,如Box Tracking, Instant Motion Tracking, Objectron, KNIFT, AutoFlip, MediaSequence, Youtube 8M等,但同時也新增了對文字及聲音辨識的支持。最新支持的解決方案如圖一所示。



圖一 : MediaPipe解決方案。[4]
圖一 : MediaPipe解決方案。[4]

如果大家想感受一下這些功能,新版官網有提供線上體驗版[4],不必安裝,不用寫程式,可直接上傳測試影像或聲音檔案,或直接開啟電腦上的網路攝影機或麥克風就能進行測試。


如果想要自己寫點程式來玩玩的朋友,使用Python開發算是最方便的,以下就以Windows為例進行說明。首先在自己的電腦上先安裝Python(3.7 ~ 3.10版),再使用PIP(19.0版以上)安裝即可。建議先在自己電腦上開一個Python虛擬環境再安裝,以免污染原先Python的開發環境。另外由於後續要使用到模擬鍵盤滑鼠輸入的功能,所以這裡會一起安裝PyAutoGUI[5]的套件。完整安裝步驟如下所示。



# 切換到想要工作的磁碟 x (可略過,可直接使用啟動命令列模式時的路徑)


x:


# 建立Python虛擬環境


python -m venv mediapipe_env


# 啟動Python虛擬環境


mediapipe_env\Scripts\activate


# 進入後命令列提示會變成 (mediapipe_env) x:\


# 安裝Mediapipe (已包含numpy, matplotlib, opencv-contrib_python等),可忽略版本設定(==0.10.0)則會安裝最新版本。


pip install -q mediapipe==0.10.0


# 安裝PyAutoGui (處理鍵盤輸入及訊息輸出)


pip install pyautogui


# 檢查已安裝套件 (可略過)


pip list


# 啟動Python檢查模組是否安裝正確


python


>>> import mediapipe as mp


>>> import pyautogui as ag


>>> import cv2


>>> print(mp.__version__) # 列印MediaPipe版本 ==> 0.10.0


>>> print(ag.__version__) # 列印PyAutoGui版本 ==> 0.9.53


>>> print(cv2.__version__) # 列印OpenCV版本 ==> 4.7.0


#按 Ctrl+Z 再按Enter 結束Python程式編輯環境


# 於命令列輸入 deactivate 即可退出Python虛擬環境回到 x:\



2.手部特徵點提取

目前MediaPipe可協助提取手部特徵點(Hand Landmark)共21點,完整的節點及名稱如Fig. 2所示[6],而左手和右手也是可以區分出來的。如果想要練習一下程式但又還沒安裝開發環的朋友,官方也很貼心的提Colab版本給大家試一下,使用前請先登入自己的Google帳號,點擊下列網址開啟範例程式,再點擊選單「執行階段」下的「全部執行」便可得到測試結果,看到載入的影像已被繪上手部特徵點及骨架了,如圖二左所示。


Google Colab範例程式:



圖二 : 手部特徵點(Hand Landmark)定義及偵測結果示意圖。
圖二 : 手部特徵點(Hand Landmark)定義及偵測結果示意圖。

整個程式架構非常簡單,略過下載模型、測試影像及繪製特徵點到影像函式外,只需理解最後一格的「Run inference and visualizing the results」就足夠了。大致分為五個動作,如程式註解說明。如果想更完整理解,可參考官方提供之說明[7]。



# 步驟一:導入必要函式庫


import mediapipe as mp


from mediapipe.tasks import python


from mediapipe.tasks.python import vision


# 步驟二:建立手部特徵點物件


# 載入手部特徵點偵測模型


base_options = python.BaseOptions(model_asset_path=’hand_landmarker.task’)


# 建立手部特徵點偵測基本參數


options = vision.HandLandmarkerOptions(base_options=base_options, num_hands=2)


# 建立手部特徵點偵測器


detector = vision.HandLandmarker.create_from_options(options)


# 步驟三:載入測試影像(可自行修改成待測試影像名稱)


image = mp.Image.create_from_file(“image.jpg”)


# 步驟四:偵測手部特徵點


detection_result = detector.detect(image)


# 步驟五:產生結果影像並顯示


# 將偵測到的結果(特徵點及連結線)繪製到新影像上


annotated_image = draw_landmarks_on_image(image.numpy_view(), detection_result)


# 顯示時需將色彩格式RGB轉回BGR才能正確顯示。


cv2_imshow(cv2.cvtColor(annotated_image, cv2.COLOR_RGB2BGR))



3.常用靜態手勢辨識

有了這些手部特徵點後,還可以更進一步把特定形狀解讀為有意義的靜態手勢,但如果要自己解讀21個特徵點的相對位置來辨識手勢,可能不是這麼容易,所以MediaPipe提供了七種常見手勢辨識[8],以便大家直接使用,包括:


1. None 未知手勢


2. Closed_Fist 握拳


3. Open_Palm 打開手掌


4. Pointing_Up 食指向上


5. Thumb_Down 姆指向下(爛)


6. Thumb_Up 姆指向上(讚)


7. Victory 勝利(食指、中指呈V字型)


8. ILoveYou 愛心(姆指、食指呈愛心)


同樣地,這裡也有提供Colab格式的範例,


如下連結



圖三 : 常見手勢辨識(Gesture Recognitiaon)定義及辨識結果示意圖。
圖三 : 常見手勢辨識(Gesture Recognitiaon)定義及辨識結果示意圖。

而程式的內容和手部特徵點偵測類似,只是換了模型檔「gesture_recognizer.task」和繪製結果影像的函式和輸出辨識結果及置信度,這裡就略過說明,如果想更完整理解,可參考官方提供之說明[9]。


4.模擬鍵盤滑鼠輸出

接下來為了讓手勢(影像)能取代手按鍵盤及移動滑鼠,這裡使用了一個常見的Python套件包PyAutoGUI[5]。我們可以透過它來操作一些滑鼠及鍵盤動作,如下幾個範例。



import pyautogui as ag


ag.PAUSE=3 # 延遲3秒,方便切換工作視窗


ag.position() # 讀取目前滑鼠游標位置並輸出


ag.moveTo(x,y,n) # 用n秒把滑鼠座標移到(x,y)位置


ag.click() # 模擬滑鼠點擊


# 按住滑鼠 key 再拖曳到座標 x,y 位置,key 可為滑鼠三個按鍵 ‘left’, ‘middle’, ‘right’


ag.dragTo(x, y, button=’key’)


# 模擬按下 key 鍵,如’1′, ‘k’, ‘f1’, ‘shift’ 等


# 更多按鍵(key)的名稱可參考 https://pyautogui.readthedocs.io/en/latest/keyboard.html#keyboard-keys


ag.keyDown(‘key’) # 按下 key


ag.keyUp(‘key’) # 放開 key


ag.press(‘key’) # 點擊 key, 包括 keyDown, keyUp


ag.press(‘key’, presses=n) # 按下 key n秒後再放開


# 同時按下 ctrl, shift, esc ,相當於執行下面六個動作


# ag.keyDown(‘ctrl’)


# ag.keyDown(‘shift’)


# ag.keyDown(‘esc’)


# ag.keyUp(‘esc’)


# ag.keyUp(‘shift’)


# ag.keyUp(‘ctrl’)


ag.hotkey(‘ctrl’, ‘shift’, ‘esc’)



更多鍵盤按鍵的名稱可參考[10]。


5.手勢控制簡報播放範例

一般我們在使用Microsoft PowerPoint進行簡報時常會搭配一組無線的簡報操作遙控器,方便我們控制下一頁的播放。這裡我們將利用網路攝影機作為影像輸入裝置,並採用 MediaPipe 的手勢辨識套件來偵測控制播放的手勢,最後使用PyAutoGUI來控制滑鼠、鍵盤,取代簡報遙控器播放簡報。


首先我們要知道PowerPoint 常用快捷鍵,如下所示。


 【Page Up】或【↑】或【←】 上一張投影片


 【Page Down】或【↓】或【→】 下一張投影片


 【F5】 開始播放簡報


 【Home】 回到簡報首頁


 【Esc】 結束簡報


接下來的範例中,我們僅簡單定義使用「打開手掌」的手勢代替【Page Down】按鍵按下,作為播放下一頁的動作。當然大家可自行選用比較好操作的手勢並修改相關程式,也可以自行增加其它手勢來控制其它動作。


另外由於以上章節的範例都必須在雲端Google Colab上運行,不方便控制本地(電腦)端 PowerPoint的播放,所以這裡要改用Python程式來運行。運行前請先確認已依第一節文章所述,將開發環境建置好並依下列步驟啟動及運行程式,如圖四所示。



1. 進入命令列模式 cmd,注意不要讓視窗最大化,可調整到畫面2/3大小大約置於螢幕中間即可。


2. 切換到想要工作的磁碟 x (依安裝磁碟決定)


x:


3. 啟動 Python 虛擬環境


mediapipe_env\Scripts\activate


4. 下載本範例並進入範例路徑


git clone –depth=1 https://github.com/OmniXRI/PPT_Gesture_Demo.git


cd PPT_Gesture_Demo


5. 開啟 PowerPoint 簡報並最大化


6. 執行範例程式,執行後游標會移到視窗最上方並點擊 PowerPoint 檔案並進入播放模式。而範例程式及視窗會自動移到背景執行(不可視)。


python ppt_gesture_demo.py


7. 當偵測到「打開手掌」動作就能自動播放下一頁。


8. 當欲結束控制時,點擊網路攝影機視窗後,再按「q」或「ESC」鍵即可離開程式




圖四 : 程式運行結果示意圖。
圖四 : 程式運行結果示意圖。

完整範例程式連結及說明,如下所示。


https://github.com/OmniXRI/PPT_Gesture_Demo



# ppt_gesture_demo.py


#


# 利用網路攝影機作為影像輸入裝置,並採用 MediaPipe 的手勢辨識套件來偵測控制播放的手勢,最後使用 PyAutoGUI 來控制滑鼠、鍵盤,取代簡報遙控器播放簡報。


# 作者:Jack OmniXRI, 2023/05/15


# 引入必要函式庫


import mediapipe as mp


from mediapipe.tasks import python


from mediapipe.tasks.python import vision


from mediapipe.framework.formats import landmark_pb2


from matplotlib import pyplot as plt


import cv2 # 引入 OpenCV 函式庫


import numpy # 引入numpy函式庫


import pyautogui as ag # 引入PyAutoGui函式庫


# 宣告繪製手勢相關物件


mp_hands = mp.solutions.hands


mp_drawing = mp.solutions.drawing_utils


mp_drawing_styles = mp.solutions.drawing_styles


# 定義顯示手勢及手部特徵點函式 display_gesture_and_hand_landmarks


# 輸入原始影像、手勢及手部特徵點資料


# 輸出繪製好手部特徵點及連結之影像及手勢名稱


def display_gesture_and_hand_landmarks(images, gestures, hand_landmarks):


image = images.numpy_view() # 將numpy格式影像轉回opencv格式影像


top_gestures = [gestures for gestures in gestures] # 取得手勢資料陣列


hand_landmarks_list = [hand_landmarks for hand_landmarks in hand_landmarks] # 取得手部21個特徵點資料


title = ” # 存放手勢名稱及置信度字串


gesture_name = ” #存放手勢名稱


# 若手勢內容不空則產生「手勢名稱加置信度」字串


if numpy.size(top_gestures) != 0:


gesture_name = top_gestures[0][0].category_name


gesture_score = top_gestures[0][0].score


title = f”{gesture_name}({gesture_score:.2f})”


annotated_image = image.copy() # 複製一份影像再開始繪製內容


# 若手部特徵點座標不空則繪製點及線於影像上


if numpy.size(hand_landmarks_list) != 0:


# 逐點繪製手部特徵點及連結線段


for hand_landmarks in hand_landmarks_list:


hand_landmarks_proto = landmark_pb2.NormalizedLandmarkList()


hand_landmarks_proto.landmark.extend([


landmark_pb2.NormalizedLandmark(x=landmark.x, y=landmark.y, z=landmark.z) for landmark in hand_landmarks


])


mp_drawing.draw_landmarks(


annotated_image,


hand_landmarks_proto,


mp_hands.HAND_CONNECTIONS,


mp_drawing_styles.get_default_hand_landmarks_style(),


mp_drawing_styles.get_default_hand_connections_style())


# 繪製手勢名稱及置信度字串到影像左上角


cv2.putText(annotated_image, f”{title}”,


(20, 30), cv2.FONT_HERSHEY_DUPLEX,


1, (0, 0, 255), 1, cv2.LINE_AA)


# 回傳結果影像及手勢名稱


return annotated_image, gesture_name


# 先開啟PowerPoint 並最大化等待啟動(F5鍵)及操作命令


# 令滑鼠移到PowerPoint視窗位置並點擊


ag.moveTo(960, 10, 1)


ag.click()


ag.press(‘f5′)


# 宣告手勢辨識器及初使化相關參數


base_options = python.BaseOptions(model_asset_path=’gesture_recognizer.task’)


options = vision.GestureRecognizerOptions(base_options=base_options)


recognizer = vision.GestureRecognizer.create_from_options(options)


# 開啟網路攝影機擷取影像


cap = cv2.VideoCapture(0)


# 開始連續取像並推論及控制簡報播放


while(True):


# 從網路攝影機擷取一張影像


ret, frame = cap.read()


# 轉換影像格式以滿足 MediaPipe


mp_image = mp.Image(image_format=mp.ImageFormat.SRGB, data=frame)


# 進行手勢辨識並取得手勢及手部特徵資料


recognition_result = recognizer.recognize(mp_image)


top_gesture = recognition_result.gestures


hand_landmarks = recognition_result.hand_landmarks


# 呼叫顯示手勢及手部特徵點函式並取得結果影像及手勢名稱


annotated_image, gesture_name = display_gesture_and_hand_landmarks(mp_image, top_gesture, hand_landmarks)


cv2.imshow(‘frame’, annotated_image)


# 若偵測到「打開手掌」手勢則模擬「Page Down」按鍵按下,令簡報往下一頁播放。


# 模擬按鍵按下後,等待1秒,再繼續偵測手勢,以免重覆觸發。


# 這裡的手勢可換成其它手勢,如 “Closed_Fist”, “Open_Palm”, “Pointing_Up”, “Thumb_Down”, “Thumb_Up”, “Victory”等。


if gesture_name == “Open_Palm”:


ag.press(‘pagedown’)


ag.PAUSE = 1


# 當按下 q 或 ESC 鍵則離開迴圈


key = cv2.waitKey(1)


if key == ord(‘q’) or key == 27:


break


# 釋放網路攝影機


cap.release()


# 關閉所有 OpenCV 視窗


cv2.destroyAllWindows()



小結

Google MediaPipe是一種很輕量的AI人機互動工具函式庫,此次更新版讓大家很容易上手及應用。本文範例只是牛刀小試了一下手勢辨識,讓播放簡報瞬間就變得很神奇,只需揮揮手就能切換頁面,不用再拿著簡報播放遙控器。相信在大家的巧思下,未來一定可以開發出更多不一樣的用法,打造人機互動新境界。


(本文由VMAKER授權轉載;連結原文網址


參考文獻


[1] Google MediaPipe (新版官網)


https://developers.google.com/mediapipe


[2] Google MediaPipe (舊版官網)


https://google.github.io/mediapipe/


[3] Google MediaPipe Github


https://github.com/google/mediapipe


[4] Google MediaPipe Demos


https://mediapipe-studio.webapps.google.com


[5] PyAutoGUI documentation


https://pyautogui.readthedocs.io/en/latest/index.html


[6] Google MediaPipe – Hand landmark detection guide


https://developers.google.com/mediapipe/solutions/vision/hand_landmarker


[7] Google MediaPipe – Hand landmarks detection guide for Python


https://developers.google.com/mediapipe/solutions/vision/hand_landmarker/python


[8] Google MediaPipe – Gesture recognition task guide


https://developers.google.com/mediapipe/solutions/vision/gesture_recognizer


[9] Google MediaPipe – Gesture recognition guide for Python


https://developers.google.com/mediapipe/solutions/vision/gesture_recognizer/python


[10] PyAutoGUI – Keyboard Control Functions – KEYBOARD_KEYS


https://pyautogui.readthedocs.io/en/latest/keyboard.html#keyboard-keys


[11] Github / OmniXRI – PPT_Gesture_Demo


https://github.com/OmniXRI/PPT_Gesture_Demo


延伸閱讀


[A] CAVEDU 教育團隊,Python程式打造Google MediaPipe 深蹲偵測互動遊戲


https://makerpro.cc/2023/03/google-mediapipe-squat-detection/


[B] CAVEDU 教育團隊,Google Mediapipe 深蹲偵測 結合 Arduino 首次接觸就上手


https://makerpro.cc/2022/06/use-mediapipe-to-do-squat-pose-detection/


[C] CAVEDU 教育團隊,Google Mediapipe 手勢控制LED呼吸燈


https://makerpro.cc/2022/03/use-google-mediapipe-to-make-a-gesture-recognition-control-led-light/


[D] CAVEDU 教育團隊,在Jetson Nano上執行Google Mediapipe 立即可用的辨識方案超好用!


https://makerpro.cc/2021/08/execute-google-mediapipe-on-jetson-nano/


相關文章
Blues推一年免費衛星通訊的Starnote IIoT模組
用ESP32實現可攜式戶外導航裝置與室內空氣監測儀
學童定位的平價機器人教材Arduino Alvik
【Maker玩AI】用Roboflow + Ultralytics HUB訓練與管理 YOLO模型
Arduino推出支援Elastic的函式庫
comments powered by Disqus
相關討論
  相關新聞
» Seagate發布再生能源使用及實踐永續循環成效
» 宜鼎獨創MIPI over Type-C解決方案突破技術侷限,改寫嵌入式相機模組市場樣貌
» 英業達以AI科技實踐永續 攜手台大保護雲霧林生物多樣性
» 震旦研發ESG綠色報表 協助企業綠色減碳
» 研華AIoV智慧車聯網解決方案 打造智慧交通與商用車國家隊


刊登廣告 新聞信箱 讀者信箱 著作權聲明 隱私權聲明 本站介紹

Copyright ©1999-2024 遠播資訊股份有限公司版權所有 Powered by O3  v3.20.2048.3.142.12.240
地址:台北數位產業園區(digiBlock Taipei) 103台北市大同區承德路三段287-2號A棟204室
電話 (02)2585-5526 #0 轉接至總機 /  E-Mail: webmaster@ctimes.com.tw