账号:
密码:
最新动态
产业快讯
CTIMES / 文章 /
Google MediaPipe快速上手 ━ 浮空手势也能用来当作简报播放器
【vMaker Edge AI专栏 #05】

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

浏览人次:【4452】

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范例程式: https://colab.research.google.com/github/googlesamples/mediapipe/blob/main/examples/hand_landmarker/python/hand_landmarker.ipynb



图二 : 手部特徵点(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格式的范例,如下连结。


https://colab.research.google.com/github/googlesamples/mediapipe/blob/main/examples/gesture_recognizer/python/gesture_recognizer.ipynb#scrollTo=Iy4r2_ePylIa



图三 : 常见手势辨识(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/


相关文章
MCX A:通用MCU和FRDM开发平台
用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.1.HK84R8A0O62STACUKY
地址:台北数位产业园区(digiBlock Taipei) 103台北市大同区承德路三段287-2号A栋204室
电话 (02)2585-5526 #0 转接至总机 /  E-Mail: webmaster@ctimes.com.tw