OpenCV学习:MediaPipe 手部关键点检测
前言:前面我们学习了基于 dlib 的人脸检测、关键点检测、换脸等技术。本篇我们将引入另一个强大的计算机视觉库——MediaPipe,学习它在手部关键点检测方面的应用。MediaPipe 是 Google 开发的多媒体机器学习框架,提供了开箱即用的手部、人脸、姿态等检测模型,使用非常简单,检测精度也很高。
目录
- 一、MediaPipe 简介
- 二、手部识别模块
- 三、核心参数详解
- 四、完整代码
- 五、关键点说明
- 六、总结
一、MediaPipe 简介
1.1 什么是 MediaPipe?
MediaPipe 是 Google 开发并开源的一个跨平台机器学习框架,提供了多种预训练模型,可以直接用于:
| Hands | 手部关键点检测 |
| Face Detection | 人脸检测 |
| Face Mesh | 人脸网格(468 个关键点) |
| Pose | 人体姿态检测 |
| Holistic | 全身关键点检测 |
1.2 MediaPipe 的优势
| 开箱即用 | 内置预训练模型,无需自己训练 |
| 速度快 | 专为实时应用优化,手机端也能流畅运行 |
| 精度高 | 手部检测能识别 21 个关键点 |
| 跨平台 | 支持 Windows、Linux、macOS、Android、iOS |
1.3 安装
pip install mediapipe==0.10.21
版本说明:MediaPipe 版本迭代较快,不同版本 API 略有差异。本案例使用 0.10.21,建议保持一致。
二、手部识别模块
2.1 模块导入
import cv2
import mediapipe as mp
mp_drawing = mp.solutions.drawing_utils # 绘图模块
mp_hands = mp.solutions.hands # 手部识别模块
| mp.solutions.drawing_utils | 绘图工具,将关键点绘制到图像中 |
| mp.solutions.drawing_styles | 绘图风格(颜色、粗细等) |
| mp.solutions.hands | 手部识别模块,提供 API |
2.2 初始化手部识别类
hands = mp_hands.Hands(
static_image_mode=False,
max_num_hands=2,
min_detection_confidence=0.75,
min_tracking_confidence=0.75)
2.3 处理图像
results = hands.process(frame)
process() 返回的 results 包含手部检测结果,关键属性是:
| multi_hand_landmarks | 检测到的所有手的关键点 |
| multi_handedness | 每只手的左右手信息 |
三、核心参数详解
3.1 static_image_mode
| True | 适用于静态图片的手势识别 |
| False | 适用于视频等动态识别(默认) |
区别:True 模式下,每帧图片独立检测;False 模式下,会利用前一帧的信息进行追踪。
注意:若识别的手的数量超过 max_num_hands,True 模式下识别的手会在多个手之间不停闪烁;False 模式下超出的手不会识别,系统会自动跟踪之前已经识别过的手。
3.2 max_num_hands
| int | 识别手的最大数量,默认为 2 |
3.3 min_detection_confidence
| 0.0 ~ 1.0 | 最小检测置信度,默认为 0.5 |
影响:值越小越容易识别出手,用时越短,但准确度越低;值越大识别越精准,但响应时间增加。
3.4 min_tracking_confidence
| 0.0 ~ 1.0 | 最小追踪置信度,默认为 0.5 |
影响:值越大手部追踪越准确,响应时间也越长。
3.5 参数调优建议
| 实时性要求高 | min_detection_confidence=0.5、min_tracking_confidence=0.5 |
| 精度要求高 | min_detection_confidence=0.8、min_tracking_confidence=0.8 |
| 处理单张图片 | static_image_mode=True |
| 处理视频流 | static_image_mode=False |
四、完整代码
import cv2
import mediapipe as mp
# pip install mediapipe==0.10.21
# ==================== 模块初始化 ====================
# drawing_utils:绘图模块,将关键点绘制到图像上
# hands:手部识别模块,提供 API
mp_drawing = mp.solutions.drawing_utils
mp_hands = mp.solutions.hands
# 初始化手部识别类
hands = mp_hands.Hands(
static_image_mode=False, # False 适用于视频动态识别
max_num_hands=2, # 最多识别 2 只手
min_detection_confidence=0.75, # 最小检测置信度
min_tracking_confidence=0.75) # 最小追踪置信度
# ==================== 打开摄像头 ====================
cap = cv2.VideoCapture(0, cv2.CAP_DSHOW)
while True:
ret, frame = cap.read()
if not ret:
break
h, w = frame.shape[:2] # 获取图像高度和宽度
# MediaPipe 需要 RGB 格式输入,OpenCV 默认是 BGR,所以先转换
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
# 摄像头是镜像的,水平翻转让画面更自然
frame = cv2.flip(frame, 1)
# 手部检测
results = hands.process(frame)
# 转回 BGR 格式,方便 OpenCV 显示
frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR)
# ==================== 绘制关键点 ====================
if results.multi_hand_landmarks:
for hand_landmarks in results.multi_hand_landmarks:
# 遍历 21 个手部关键点,绘制编号
for i in range(len(hand_landmarks.landmark)):
x = hand_landmarks.landmark[i].x # 归一化的 x 坐标(0~1)
y = hand_landmarks.landmark[i].y # 归一化的 y 坐标(0~1)
z = hand_landmarks.landmark[i].z # 深度信息
print(f'关键点{i}:', x, y, z)
# 将归一化坐标乘以图像宽高,转为像素坐标
cv2.putText(frame, str(i),
(int(x * w), int(y * h)),
cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
# 绘制手部关键点连接线
mp_drawing.draw_landmarks(frame,
hand_landmarks,
mp_hands.HAND_CONNECTIONS)
cv2.imshow('MediaPipe Hands', frame)
# 按 ESC 键退出
if cv2.waitKey(1) & 0xFF == 27:
break
cap.release()
cv2.destroyAllWindows()
五、关键点说明
5.1 手部 21 个关键点
MediaPipe 手部检测会返回 21 个关键点,分布如下:
| 0 | 手腕 | 11 | 中指根部 |
| 1 | 拇指根部 | 12 | 中指第一关节 |
| 2 | 拇指第一关节 | 13 | 中指第二关节 |
| 3 | 拇指第二关节 | 14 | 中指指尖 |
| 4 | 拇指指尖 | 15 | 无名指根部 |
| 5 | 食指根部 | 16 | 无名指第一关节 |
| 6 | 食指第一关节 | 17 | 无名指第二关节 |
| 7 | 食指第二关节 | 18 | 无名指指尖 |
| 8 | 食指指尖 | 19 | 小指根部 |
| 9 | 中指根部 | 20 | 小指指尖 |
| 10 | 中指第一关节 | — | — |
5.2 坐标说明
| x | 归一化坐标,0~1 之间,需要乘以图像宽度 |
| y | 归一化坐标,0~1 之间,需要乘以图像高度 |
| z | 深度信息,以手腕为原点,数值越小越靠近摄像头 |
5.3 HAND_CONNECTIONS
mp_hands.HAND_CONNECTIONS 定义了关键点之间的连接关系,用于绘制骨架连线。
5.4 应用场景
| 手势控制 | 通过手势控制设备或游戏 |
| 手语翻译 | 识别手语动作并翻译 |
| 虚拟试戴 | 手部关键点定位,用于戒指、手表试戴 |
| 动作分析 | 分析手部动作,如弹钢琴、打字 |
| AR/VR 交互 | 手部追踪实现自然交互 |
六、总结
核心函数速查
| mp.solutions.hands.Hands(…) | 初始化手部识别类 |
| hands.process(frame) | 处理图像,返回检测结果 |
| results.multi_hand_landmarks | 获取检测到的手部关键点 |
| mp_drawing.draw_landmarks() | 绘制关键点和连接线 |
| hand_landmarks.landmark[i].x/y/z | 获取第 i 个关键点的坐标 |
核心参数速查
| static_image_mode | False | True 适合静态图片,False 适合视频 |
| max_num_hands | 2 | 最大识别手数 |
| min_detection_confidence | 0.5 | 最小检测置信度 |
| min_tracking_confidence | 0.5 | 最小追踪置信度 |
注意事项
| 图像格式 | MediaPipe 需要 RGB 输入,OpenCV 默认 BGR,需要转换 |
| 坐标归一化 | 关键点坐标是 0~1 的归一化值,需乘以图像宽高 |
| 镜像翻转 | 摄像头建议水平翻转,画面更自然 |
| 实时性能 | 视频模式下,min_detection_confidence 不宜过高 |
| 退出方式 | 按 ESC 键退出循环 |
系列直达
- 上篇:OpenCV学习:仿射变换与换脸术
- 本篇:OpenCV学习:MediaPipe 手部关键点检测(本文)
- 下篇:敬请期待
网硕互联帮助中心



评论前必须登录!
注册