MediaPipe Holistic: 人体姿态、人脸与手部关键点实时检测实战
完整代码在最下方!!!
## 一、引言
随着计算机视觉技术的快速发展,人体姿态识别在人机交互、健身指导、动作捕捉等领域得到了广泛应用。谷歌开发的MediaPipe库以其轻量级、高精度的特性,成为实时人体关键点检测的热门选择。本文将详细介绍如何使用MediaPipe的Holistic解决方案,同时检测和绘制人体姿态、人脸和手部的关键点,并通过OpenCV实现摄像头实时处理。
## 二、环境准备
在开始之前,需要安装以下Python库:
pip install mediapipe opencv-python
MediaPipe负责关键点检测,OpenCV用于图像处理和显示。安装完成后,我们就可以开始编写代码了。
## 三、核心代码解析
### 3.1 导入必要的库
import mediapipe as mp # 导入MediaPipe库,用于实时计算机视觉任务
import cv2 # 导入OpenCV库,用于图像处理
import os # 导入os模块,用于文件路径处理
这部分代码导入了我们需要的三个核心库:MediaPipe用于人体关键点检测,OpenCV用于图像读取和显示,os用于文件路径处理。
### 3.2 初始化绘图工具和模
# 画图工具
mp_drawing = mp.solutions.drawing_utils # 导入MediaPipe的绘图工具,用于在图像上绘制关键点
mp_drawing_styles = mp.solutions.drawing_styles # 导入MediaPipe的绘图样式
drawing_spec = mp_drawing.DrawingSpec(thickness=1, circle_radius=1) # 设置绘图规格,包括线条厚度和关键点圆圈半径
# 导入MediaPipe的全局解决方案
mp_holistic = mp.solutions.holistic # 选择MediaPipe的全局解决方案,用于同时检测人脸、姿态和手部
holistic = mp_holistic.Holistic(min_detection_confidence=0.5,
min_tracking_confidence=0.5) # 创建Holistic模型实例,设置最低检测置信度和跟踪置信度
这段代码完成了两个重要工作:
- 配置了绘图工具,设置了关键点和连接线的样式
- 初始化了Holistic模型,这是MediaPipe中能够同时检测人脸、人体姿态和双手的综合解决方案
其中`min_detection_confidence`和`min_tracking_confidence`参数分别设置了检测和跟踪的置信度阈值,值越高,检测结果越严格但可能漏掉一些边界情况。
### 3.3 图像文件处理
# 读取一张图片
image_path = "./ski.jpg"
# 检查文件是否存在
if os.path.exists(image_path):
im = cv2.imread(image_path) # 使用OpenCV读取指定路径的图片
# 检查图像是否成功读取
if im is not None:
try:
results = holistic.process(im) # 使用Holistic模型处理图片,获取检测结果
# 关节点渲染
# 画脸
mp_drawing.draw_landmarks(
im, # 图像
results.face_landmarks, # 人脸关键点检测结果
mp_holistic.FACEMESH_CONTOURS, # 人脸轮廓连接点
landmark_drawing_spec=None, # 不特别指定关键点绘图规格 connection_drawing_spec=mp_drawing_styles.get_default_face_mesh_contours_style() # 使用默认的人脸轮廓连接线样式
)
# 画人体骨架
mp_drawing.draw_landmarks(
im, # 图像
results.pose_landmarks, # 人体姿态关键点检测结果
mp_holistic.POSE_CONNECTIONS, # 人体姿态连接点
landmark_drawing_spec=mp_drawing_styles.get_default_pose_landmarks_style() # 使用默认的人体姿态关键点样式
)
cv2.imshow("image", im) # 使用OpenCV显示图像
cv2.waitKey(0) # 等待用户按下任意键
cv2.destroyAllWindows() # 关闭所有窗口
except Exception as e:
print(f"处理图像时出错: {e}")
else:
print(f"无法读取图像文件: {image_path}")
else:
print(f"图像文件不存在: {image_path}")
print("跳过图像处理部分,直接进入摄像头模式")
这部分代码实现了图像文件的处理:
1. 首先检查指定路径的图像文件是否存在
2. 如果存在,尝试读取图像并使用Holistic模型进行处理
3. 在图像上绘制检测到的人脸轮廓和人体骨架
4. 显示处理后的图像,并等待用户按键关闭
5. 加入了完善的错误处理机制,确保程序不会因文件不存在或读取失败而崩溃
### 3.4 摄像头实时检测
# 打开摄像头
try:
cap = cv2.VideoCapture(0) # 打开默认摄像头(通常为0)
# 检查摄像头是否成功打开
if not cap.isOpened():
print("无法打开摄像头")
else:
print("摄像头已成功打开,按ESC键退出")
while cap.isOpened():
success, image = cap.read() # 从摄像头读取一帧图像
if not success: # 如果读取失败
print("忽略空的摄像头帧")
continue # 继续读取下一帧
try:
image.flags.writeable = False # 设置图像为只读,避免在绘制过程中修改图像数据
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) # 将图像从BGR颜色空间转换为RGB颜色空间,因为MediaPipe模型需要RGB图像
results = holistic.process(image) # 使用Holistic模型处理图像
left_hand_landmarks = results.left_hand_landmarks # 获取左手关键点检测结果
right_hand_landmarks = results.right_hand_landmarks # 获取右手关键点检测结果
image.flags.writeable = True # 恢复图像的写权限
# 在图像上绘制关键点
mp_drawing.draw_landmarks(image, results.pose_landmarks, mp_holistic.POSE_CONNECTIONS,
mp_drawing_styles.get_default_pose_landmarks_style()) # 绘制人体姿态
mp_drawing.draw_landmarks(image, results.face_landmarks, mp_holistic.FACEMESH_CONTOURS, drawing_spec,
mp_drawing_styles.get_default_face_mesh_contours_style()) # 绘制人脸
# 绘制左手(只有检测到左手时才绘制)
if left_hand_landmarks:
mp_drawing.draw_landmarks(image, left_hand_landmarks, mp_holistic.HAND_CONNECTIONS,
mp_drawing_styles.get_default_hand_landmarks_style(),
mp_drawing_styles.get_default_hand_connections_style())
# 绘制右手(只有检测到右手时才绘制)
if right_hand_landmarks:
mp_drawing.draw_landmarks(image, right_hand_landmarks, mp_holistic.HAND_CONNECTIONS,
mp_drawing_styles.get_default_hand_landmarks_style(),
mp_drawing_styles.get_default_hand_connections_style())
image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR) # 将图像从RGB颜色空间转换回BGR颜色空间,以便OpenCV显示
image = cv2.flip(image, 1) # 水平翻转图像(镜像效果)
cv2.imshow('MediaPipe Holistic', image) # 使用OpenCV显示图像
# 如果按下Esc键(ASCII码为27)退出循环
if cv2.waitKey(5) & 0xFF == 27:
break
except Exception as e:
print(f"处理摄像头帧时出错: {e}")
finally:
# 确保在程序结束时释放摄像头并关闭所有窗口
cap.release()
cv2.destroyAllWindows()
print("程序已退出,摄像头已释放")
摄像头实时检测部分是本程序的核心,主要流程如下:
1. 打开默认摄像头(设备ID为0)
2. 进入循环,不断从摄像头读取图像帧
3. 对每一帧图像进行处理:
- 将图像从BGR格式转换为RGB格式(MediaPipe需要RGB输入)
- 使用Holistic模型检测关键点
- 在图像上绘制检测到的人体姿态、人脸和手部关键点
- 将图像转换回BGR格式并水平翻转(实现镜像效果)
- 显示处理后的图像
4. 监听键盘输入,按下ESC键时退出程序
5. 使用try-finally结构确保程序退出时正确释放摄像头资源
## 四、代码优化建议
原代码已经实现了基本功能,但还有一些可以优化的地方:
### 4.1 添加FPS显示
在实时处理时,显示帧率(FPS)可以帮助评估系统性能:
import time
# 在摄像头循环中添加
start_time = time.time()
# ... 处理图像的代码 ...
fps = 1.0 / (time.time() - start_time)
cv2.putText(image, f'FPS: {int(fps)}', (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
### 4.2 参数可配置化
将关键参数提取为配置变量,便于调整和测试:
# 配置参数
IMAGE_PATH = "./ski.jpg"
CAMERA_ID = 0
MIN_DETECTION_CONFIDENCE = 0.5
MIN_TRACKING_CONFIDENCE = 0.5
ESC_KEY = 27
### 4.3 添加退出提示和帮助信息
为提升用户体验,可以添加简单的帮助信息:
print("=== MediaPipe Holistic 实时检测程序 ===")
print("快捷键:")
print(" ESC - 退出程序")
print(" 空格 - 暂停/继续检测")
## 五、运行效果展示
运行程序后,预期效果如下:

1. 如果指定路径的图像文件存在,程序会先显示处理后的静态图像,图像上会绘制出人脸轮廓和人体骨架的关键点
2. 按下任意键后,程序会尝试打开摄像头,进入实时检测模式
3. 在实时检测模式下,程序会实时显示摄像头捕获的画面,并在画面上绘制出检测到的人体姿态、人脸和手部关键点
4. 按下ESC键可以退出程序
## 六、应用场景与扩展
MediaPipe Holistic解决方案的应用场景非常广泛,包括但不限于:
1. **健身指导**:实时检测用户动作是否标准
2. **虚拟现实**:为VR/AR应用提供人体姿态跟踪
3. **手势识别**:实现无需触摸的人机交互
4. **安防监控**:异常行为检测
5. **影视制作**:简化动作捕捉流程
在此基础上,我们还可以进行以下扩展:
- 结合机器学习算法,实现特定动作的识别
- 添加数据记录功能,保存检测结果用于后续分析
- 开发多人检测模式,同时跟踪多个用户
- 部署到移动设备,实现移动端的实时检测
## 七、总结
本文详细介绍了如何使用MediaPipe的Holistic解决方案,结合OpenCV实现人体姿态、人脸和手部关键点的实时检测。通过完善的错误处理机制和资源管理,确保了程序的稳定性和可靠性。这个案例展示了计算机视觉技术在人体姿态识别领域的应用潜力,希望能为读者提供有益的参考。
完整代码
import mediapipe as mp # 导入MediaPipe库,用于实时计算机视觉任务
import cv2 # 导入OpenCV库,用于图像处理
import os # 导入os模块,用于文件路径处理
# 画图工具
mp_drawing = mp.solutions.drawing_utils # 导入MediaPipe的绘图工具,用于在图像上绘制关键点
mp_drawing_styles = mp.solutions.drawing_styles # 导入MediaPipe的绘图样式
drawing_spec = mp_drawing.DrawingSpec(thickness=1, circle_radius=1) # 设置绘图规格,包括线条厚度和关键点圆圈半径
# 导入MediaPipe的全局解决方案
mp_holistic = mp.solutions.holistic # 选择MediaPipe的全局解决方案,用于同时检测人脸、姿态和手部
holistic = mp_holistic.Holistic(min_detection_confidence=0.5,
min_tracking_confidence=0.5) # 创建Holistic模型实例,设置最低检测置信度和跟踪置信度
# 读取一张图片
image_path = "./ski.jpg"
# 检查文件是否存在
if os.path.exists(image_path):
im = cv2.imread(image_path) # 使用OpenCV读取指定路径的图片
# 检查图像是否成功读取
if im is not None:
try:
results = holistic.process(im) # 使用Holistic模型处理图片,获取检测结果
# 关节点渲染
# 画脸
mp_drawing.draw_landmarks(
im, # 图像
results.face_landmarks, # 人脸关键点检测结果
mp_holistic.FACEMESH_CONTOURS, # 人脸轮廓连接点
landmark_drawing_spec=None, # 不特别指定关键点绘图规格
connection_drawing_spec=mp_drawing_styles.get_default_face_mesh_contours_style() # 使用默认的人脸轮廓连接线样式
)
# 画人体骨架
mp_drawing.draw_landmarks(
im, # 图像
results.pose_landmarks, # 人体姿态关键点检测结果
mp_holistic.POSE_CONNECTIONS, # 人体姿态连接点
landmark_drawing_spec=mp_drawing_styles.get_default_pose_landmarks_style() # 使用默认的人体姿态关键点样式
)
cv2.imshow("image", im) # 使用OpenCV显示图像
cv2.waitKey(0) # 等待用户按下任意键
cv2.destroyAllWindows() # 关闭所有窗口
except Exception as e:
print(f"处理图像时出错: {e}")
else:
print(f"无法读取图像文件: {image_path}")
else:
print(f"图像文件不存在: {image_path}")
print("跳过图像处理部分,直接进入摄像头模式")
# 打开摄像头
try:
cap = cv2.VideoCapture(0) # 打开默认摄像头(通常为0)
# 检查摄像头是否成功打开
if not cap.isOpened():
print("无法打开摄像头")
else:
print("摄像头已成功打开,按ESC键退出")
while cap.isOpened():
success, image = cap.read() # 从摄像头读取一帧图像
if not success: # 如果读取失败
print("忽略空的摄像头帧")
continue # 继续读取下一帧
try:
image.flags.writeable = False # 设置图像为只读,避免在绘制过程中修改图像数据
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) # 将图像从BGR颜色空间转换为RGB颜色空间,因为MediaPipe模型需要RGB图像
results = holistic.process(image) # 使用Holistic模型处理图像
left_hand_landmarks = results.left_hand_landmarks # 获取左手关键点检测结果
right_hand_landmarks = results.right_hand_landmarks # 获取右手关键点检测结果
image.flags.writeable = True # 恢复图像的写权限
# 在图像上绘制关键点
mp_drawing.draw_landmarks(image, results.pose_landmarks, mp_holistic.POSE_CONNECTIONS,
mp_drawing_styles.get_default_pose_landmarks_style()) # 绘制人体姿态
mp_drawing.draw_landmarks(image, results.face_landmarks, mp_holistic.FACEMESH_CONTOURS, drawing_spec,
mp_drawing_styles.get_default_face_mesh_contours_style()) # 绘制人脸
# 绘制左手(只有检测到左手时才绘制)
if left_hand_landmarks:
mp_drawing.draw_landmarks(image, left_hand_landmarks, mp_holistic.HAND_CONNECTIONS,
mp_drawing_styles.get_default_hand_landmarks_style(),
mp_drawing_styles.get_default_hand_connections_style())
# 绘制右手(只有检测到右手时才绘制)
if right_hand_landmarks:
mp_drawing.draw_landmarks(image, right_hand_landmarks, mp_holistic.HAND_CONNECTIONS,
mp_drawing_styles.get_default_hand_landmarks_style(),
mp_drawing_styles.get_default_hand_connections_style())
image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR) # 将图像从RGB颜色空间转换回BGR颜色空间,以便OpenCV显示
image = cv2.flip(image, 1) # 水平翻转图像(镜像效果)
cv2.imshow('MediaPipe Holistic', image) # 使用OpenCV显示图像
# 如果按下Esc键(ASCII码为27)退出循环
if cv2.waitKey(5) & 0xFF == 27:
break
except Exception as e:
print(f"处理摄像头帧时出错: {e}")
finally:
# 确保在程序结束时释放摄像头并关闭所有窗口
cap.release()
cv2.destroyAllWindows()
print("程序已退出,摄像头已释放")
更多推荐


所有评论(0)