Mediapipe 实现手势追踪
环境:python3.8,pycharm2020
硬件:罗技c505e
Mediapipe hands
官网信息:https://google.github.io/mediapipe/solutions/hands.html
Mediapipe是谷歌开源的一个机器学习的库,里面有一些面部识别、手势识别的解决方案,且提供python、js等语言的封装。
MediaPipe Hands是一个高保真的手和手指跟踪解决方案。它使用机器学习(ML)从仅仅一帧中推断出21个3D手部关键信息。我们可以用它来实现提取手部的关键点坐标,关键点编号如下:
简单的手势追踪示例:
根据官网的文档,我们可以很快得实现一个简单的手势追踪的示例:
import cv2
import mediapipe as mp
import time
cap = cv2.VideoCapture(0, cv2.CAP_DSHOW)
mpHands = mp.solutions.hands
hands = mpHands.Hands()
mpDraw = mp.solutions.drawing_utils
# 帧率统计
pTime = 0
cTime = 0
while True:
success, img = cap.read()
imgRGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)#转换为rgb
results = hands.process(imgRGB)
print(results.multi_hand_landmarks)
if results.multi_hand_landmarks:
for handLms in results.multi_hand_landmarks:
for id, lm in enumerate(handLms.landmark):
print(id, lm)
# 获取手指关节点
h, w, c = img.shape
cx, cy = int(lm.x*w), int(lm.y*h)
cv2.putText(img, str(int(id)), (cx+10, cy+10), cv2.FONT_HERSHEY_PLAIN,
1, (0, 0, 255), 2)
mpDraw.draw_landmarks(img, handLms, mpHands.HAND_CONNECTIONS)
# 统计屏幕帧率
cTime = time.time()
fps = 1 / (cTime - pTime)
pTime = cTime
cv2.putText(img, str(int(fps)), (10, 70), cv2.FONT_HERSHEY_PLAIN, 3, (255, 0, 255), 3)
cv2.imshow("image", img)
if cv2.waitKey(2) & 0xFF == 27:
break
cap.release()
实际效果如图所示:
这里的帧数受限于摄像头的帧率。
部分api分析
Hands的初始化配置
我们在hands = mpHands.Hands()
完成对Hands初始化配置,从下面的构造函数可以看见我们可以配置的初始化参数
def __init__(self,
static_image_mode=False,
max_num_hands=2,
min_detection_confidence=0.5,
min_tracking_confidence=0.5):
- static_image_mode为静态图像模式,默认false,用于处理视频
- max_num_hands为支持检测最多手的数量
- 后面两个应该是检测和追踪的置信度阈值(概率论相关知识),当置信度小于改值时将对图像重新进行处理,该值越大结果将越准确。
手势信息的采集
results = hands.process(imgRGB)
完成对图像的处理,需要注意的是这里的输入必须为RGB格式的。
如果检测到手,那么将返回一个列表,包含21个标志点的x、y、z的值
- x、y范围为[0.1, 1], 乘以图像的宽度和高度我们就可以得到具体的像素点坐标。
- z为深度,这个值越小,就代表该坐标点接近摄像头。
results.multi_hand_landmarks
是检测到所有手的列表,对该列表进行访问我们可以得到每只手对应标志位的信息,具体示例如下,我们可以得到每个标志位的像素坐标:
if results.multi_hand_landmarks:
for handLms in results.multi_hand_landmarks:
for id, lm in enumerate(handLms.landmark):
print(id, lm)
# 获取手指关节点
h, w, c = img.shape
cx, cy = int(lm.x*w), int(lm.y*h)
cv2.putText(img, str(int(id)), (cx+10, cy+10), cv2.FONT_HERSHEY_PLAIN,
1, (0, 0, 255), 2)
具体标志点提取
有了上面的介绍,我们就很容易得到具体标志点的坐标,例如获取4标志点的信息(也就是大拇指):print(handLms.landmark[4])
相关连接
https://www.youtube.com/watch?v=9iEPzbG-xLE
https://google.github.io/mediapipe/solutions/hands.html
**后续会分享一些基于Mediapipe的应用,例如手势识别等