完整代码在最下方!!!

## 一、引言

随着计算机视觉技术的快速发展,人体姿态识别在人机交互、健身指导、动作捕捉等领域得到了广泛应用。谷歌开发的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("程序已退出,摄像头已释放")
Logo

中国智能体开发者社区,聚焦智能体与大模型开发,提供前沿资讯、实用工具链、开源项目及行业案例。通过技术沙龙、开发者大赛等活动,促进经验交流与协作,助力开发者快速构建创新智能应用。

更多推荐