开发酷炫的交互应用、控制智能家居,还是进行手语翻译,手指识别 都是其中至关重要的一步。今天,我们将深入探讨如何使用 Python 和 Google 的 MediaPipe 库,快速、精准地实现手指识别功能。
一、MediaPipe 简介:为什么是它?
在计算机视觉领域,手部识别是一个极具挑战性的任务。因为手部经常会出现遮挡、自相似(手指之间很像)以及高自由度的问题。
MediaPipe 是 Google 开源的一个跨平台、多功能多媒体机器学习模型应用框架。它提供了一系列预训练的、开箱即用的模型 ,其中就包括了非常强大的手部姿态估计模型。
选择 MediaPipe 进行手指识别的优势:
-
轻量级且高效:即使在移动设备上也能实时运行。
-
精准度高:提供了21个手部关键点的3D坐标,足以精确描述手部姿态。
-
易于使用:几行代码就能集成到你的Python项目中。
-
强大的鲁棒性:能够处理不同程度的遮挡和光照变化。
二、核心概念:21个手部关键点
MediaPipe 手部模型将一只手抽象为 21个 关键的骨节点,如下图所示。每一个点都有一个固定的索引(0-20)和明确的物理意义。
(想象一张图:一只张开的手,上面标记了从0到20的点)
-
0: 手腕
-
1-4: 拇指根部到指尖
-
5-8: 食指
-
9-12: 中指
-
13-16: 无名指
-
17-20: 小指
有了这21个点,我们不仅可以知道手的位置,还可以计算出每根手指的弯曲程度、手势的方向等。
三、实战开始:编写你的手指识别程序
让我们一步步构建一个实时的手指识别程序。
步骤 1: 环境搭建
首先,安装必要的库。MediaPipe 的强大之处在于它本身不依赖复杂的深度学习环境。
bash
pip install opencv-python mediapipe
步骤 2: 编写核心代码
创建一个Python文件(例如 hand_tracking.py),并输入以下代码:
bash
import cv2
import mediapipe as mp
# 初始化MediaPipe手部模型
mp_hands = mp.solutions.hands
mp_drawing = mp.solutions.drawing_utils
mp_drawing_styles = mp.solutions.drawing_styles
# 创建Hands对象
# 参数说明:
# static_image_mode: 如果为False,则对视频流进行优化,会追踪检测到的ID以提升性能。
# max_num_hands: 最多检测的手的数量
# model_complexity: 模型复杂度(0或1),1精度更高但更慢
# min_detection_confidence: 检测置信度阈值
# min_tracking_confidence: 追踪置信度阈值
hands = mp_hands.Hands(
static_image_mode=False,
max_num_hands=2,
model_complexity=1,
min_detection_confidence=0.5,
min_tracking_confidence=0.5
)
# 打开摄像头
cap = cv2.VideoCapture(0)
while cap.isOpened():
success, image = cap.read()
if not success:
print("Ignoring empty camera frame.")
continue
# 为了提高性能,将图像标记为不可写(传递引用)
image.flags.writeable = False
# 转换颜色空间 BGR to RGB
image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
# 处理图像并检测手部
results = hands.process(image_rgb)
# 将图像标记为可写,以便绘制
image.flags.writeable = True
image = cv2.cvtColor(image_rgb, cv2.COLOR_RGB2BGR)
# 如果检测到手部
if results.multi_hand_landmarks:
for hand_landmarks in results.multi_hand_landmarks:
# 1. 绘制手部关键点和连接线
mp_drawing.draw_landmarks(
image,
hand_landmarks,
mp_hands.HAND_CONNECTIONS, # 绘制连接线
mp_drawing_styles.get_default_hand_landmarks_style(),
mp_drawing_styles.get_default_hand_connections_style()
)
# 2. 【进阶】获取特定关键点坐标并操作
# 例如,获取食指指尖(索引为8)的坐标
index_finger_tip = hand_landmarks.landmark[mp_hands.HandLandmark.INDEX_FINGER_TIP]
# 将归一化坐标转换为像素坐标
h, w, c = image.shape
cx, cy = int(index_finger_tip.x * w), int(index_finger_tip.y * h)
# 在食指指尖画一个红色的圆
cv2.circle(image, (cx, cy), 10, (0, 0, 255), cv2.FILLED)
# 3. 【进阶】判断手指是否伸直(以食指为例)
# 思路:比较指尖(8)和指根(5)的Y坐标。如果指尖Y坐标小于指根,则认为手指向上。
index_finger_pip = hand_landmarks.landmark[mp_hands.HandLandmark.INDEX_FINGER_PIP] # 第二指节
index_finger_mcp = hand_landmarks.landmark[mp_hands.HandLandmark.INDEX_FINGER_MCP] # 指根
if index_finger_tip.y < index_finger_pip.y < index_finger_mcp.y:
cv2.putText(image, "Index Finger Up", (cx, cy-20), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
# 水平翻转图像,获得镜像视图
image = cv2.flip(image, 1)
# 显示图像
cv2.imshow('MediaPipe Hands', image)
# 按 'q' 键退出
if cv2.waitKey(5) & 0xFF == ord('q'):
break
# 释放资源
cap.release()
cv2.destroyAllWindows()
步骤 3: 运行与体验
运行这个脚本,你的摄像头将会打开。向摄像头伸出手,你会看到实时的手部关键点和连接线被绘制出来,食指指尖会有一个红点,并且当食指伸直时,会显示"Index Finger Up"的文字。
四、代码详解与进阶应用
-
hands.process()返回值:-
multi_hand_landmarks: 一个包含所有检测到的手的列表。 -
multi_handedness: 提供检测到的手是左手还是右手的信息。
-
-
坐标系统:
-
landmark.x和landmark.y是归一化坐标(0到1之间),分别表示在图像宽度和高度上的比例。需要乘以图像的实际宽高才能得到像素坐标。 -
landmark.z表示深度,原点在手腕处。值越小,离摄像头越近。
-
-
如何判断手势?
代码中展示了判断食指是否伸直的逻辑。你可以扩展这个逻辑来定义更复杂的手势。
-
判断大拇指张开:比较拇指尖(4)和拇指IP关节(3)的X坐标(或Y坐标,取决于手是左手还是右手)。
-
判断握拳:检查所有指尖是否都低于它们对应的PIP关节。
-
-
实现捏合手势:计算拇指尖和食指尖的欧几里得距离,如果距离很小,则认为发生了捏合。
bash# 示例:计算拇指和食指的捏合 thumb_tip = hand_landmarks.landmark[mp_hands.HandLandmark.THUMB_TIP] index_tip = hand_landmarks.landmark[mp_hands.HandLandmark.INDEX_FINGER_TIP] distance = ((thumb_tip.x - index_tip.x) ** 2 + (thumb_tip.y - index_tip.y) ** 2) ** 0.5 if distance < 0.05: # 阈值需要根据实际情况调整 cv2.putText(image, "Pinch", (50, 50), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 0, 0), 2) -
手势控制:用手势控制PPT翻页、视频播放/暂停。
-
虚拟现实/增强现实:在VR/AR应用中实现更自然的手部交互。
-
手语识别:组合多个手势来识别基本的手语单词。
-
远程协作:在视频会议中用手势进行标注和指示。
六、结语
MediaPipe 将曾经复杂的计算机视觉任务变得平民化。通过这篇博客,你已经学会了如何用它来搭建一个强大的实时手指识别系统。剩下的,就是发挥你的想象力,去创造下一个惊艳的交互应用了!
动手试试吧! 从修改代码、定义你自己的专属手势开始,感受计算机视觉的魅力。
10. 创意艺术:用手指在空中作画。