一、引言
在计算机视觉领域,人体关键点检测(Human Pose Estimation,HPE)一直是研究和应用的热点方向之一。随着深度学习与实时图像处理技术的发展,人体姿势估计已经从传统的 2D 检测走向了 3D 空间建模,并在 运动分析、动作识别、虚拟现实、游戏交互、医疗康复、智能健身 等众多场景中得到了广泛应用。
然而,仅仅检测人体骨架往往无法满足实际需求。人机交互过程中,手部动作与面部表情同样具有重要意义:
-
手势识别 可以实现更自然的人机控制,例如手势控制智能家居、无人机;
-
人脸关键点检测 则是表情识别、虚拟形象驱动、情感计算的重要基础;
-
姿势检测 则是全身动态捕捉、运动姿态评估的核心。
因此,一个融合 姿势(Pose)、手部(Hand)、人脸(Face) 三大关键点检测任务的多模态分析系统,不仅能提供更完整的人体建模,还能大幅提升交互体验。
本文将详细解析基于 Google Mediapipe Tasks API 封装的 HumanMultiLandmarker
类。它能够同时调用三个模型:人体骨架检测、手部关键点检测、人脸关键点检测,并在同一张画面上输出三种结果。同时,它还能将结果组织成三屏对比图(原始画面 / 骨架点线图 / 骨架叠加图),帮助开发者更直观地理解和调试模型效果。
二、技术背景
2.1 Mediapipe 简介
Mediapipe 是 Google 开源的一套跨平台、可扩展的机器学习应用框架,专注于 实时多模态感知。其核心优势在于:
-
丰富的预训练模型:包含人脸检测、手部跟踪、姿势估计、物体检测等;
-
跨平台支持:支持 Android、iOS、Web、Python、C++ 等;
-
高效实时性能:能够在 CPU、GPU 上流畅运行;
-
可组合性强:多个模块可以像“积木”一样拼装组合。
其中,人体相关的关键模型包括:
-
PoseLandmarker(人体骨架关键点检测);
-
HandLandmarker(手部 21 个关键点检测);
-
FaceLandmarker(人脸 478 个关键点检测)。
2.2 多模态人体建模的意义
单一的人体姿态估计只能提供人体整体运动的基本结构信息。但在交互系统中,手部与面部的信息同样至关重要:
-
全身:判断运动姿势,适用于健身指导、动作分析;
-
手势:识别指令,如挥手、点赞、数字手势等;
-
表情:分析情绪,驱动虚拟人物动画。
三者结合,才能形成完整的多模态建模系统。
三、代码结构概述
下面我们逐步解析 HumanMultiLandmarker
类。
class HumanMultiLandmarker:def __init__(...):# 初始化三个模型(姿势、手部、人脸)def _draw_landmarks(...):# 通用绘制函数,支持点和线def do(...):# 执行一次检测,并返回三屏对比结果
该类由 初始化方法、绘制方法、检测方法 三个部分组成。
四、初始化部分详解
self.pose_detector = vision.PoseLandmarker.create_from_options(...)
self.hand_detector = vision.HandLandmarker.create_from_options(...)
self.face_detector = vision.FaceLandmarker.create_from_options(...)
在 __init__
方法中,分别加载了三个 .task
模型文件:
-
pose_landmarker_heavy.task:人体骨架检测(33 个关键点,支持全身姿态);
-
hand_landmarker.task:手部检测(单手 21 个关键点,支持双手检测);
-
face_landmarker.task:人脸检测(478 个关键点,涵盖面部轮廓、眼睛、嘴巴、鼻子等)。
每个 Landmarker 都通过 BaseOptions
指定模型路径,再由 create_from_options
生成检测器实例。
运行模式选择 RunningMode.IMAGE
,表示输入的是单帧图像,而不是视频流或实时流。
五、绘制部分详解
绘制采用 OpenCV 的 cv2.circle
和 cv2.line
:
def _draw_landmarks(self, frame, landmarks, connections=None, color=(0, 255, 0)):h, w, _ = frame.shapefor lm in landmarks:cx, cy = int(lm.x * w), int(lm.y * h)cv2.circle(frame, (cx, cy), self.point_size, color, -1)if connections:for start, end in connections:x1, y1 = int(landmarks[start].x * w), int(landmarks[start].y * h)x2, y2 = int(landmarks[end].x * w), int(landmarks[end].y * h)cv2.line(frame, (x1, y1), (x2, y2), color, self.line_thickness)
关键点绘制
-
将归一化坐标
(lm.x, lm.y)
转换为图像像素坐标(cx, cy)
; -
通过
cv2.circle
绘制点,支持自定义颜色和大小。
连接绘制
-
如果传入了
connections
,则按照索引连接关键点; -
姿势骨架采用
solutions.pose.POSE_CONNECTIONS
; -
手部骨架采用
solutions.hands.HAND_CONNECTIONS
; -
人脸不绘制连线,避免过于密集。
六、检测与结果拼接
skeleton_only = np.zeros_like(frame) skeleton_overlay = frame.copy()
系统生成三张图像:
-
原始图像(未修改);
-
骨架图像(黑底,只绘制点和线);
-
叠加图像(原始帧上绘制骨架)。
检测过程:
pose_res = self.pose_detector.detect(mp_image) hand_res = self.hand_detector.detect(mp_image) face_res = self.face_detector.detect(mp_image)
随后分别绘制:
-
Pose → 白色线条;
-
Hand → 黄色线条;
-
Face → 红色点。
最后通过 np.concatenate
拼接为三屏对比图:
triple_frame = np.concatenate([frame, skeleton_only, skeleton_overlay], axis=1)
七、运行效果
运行后的视频帧将展示三屏效果:
-
左屏:原始摄像头画面;
-
中屏:骨架点与线条(无背景干扰);
-
右屏:骨架叠加在原始画面上。
import cv2
import numpy as np
import mediapipe as mp
from mediapipe import solutions
from mediapipe.tasks import python
from mediapipe.tasks.python import visionclass HumanMultiLandmarker:def __init__(self,pose_model="文件地址/pose_landmarker_heavy.task",hand_model="文件地址/hand_landmarker.task",face_model="文件地址/face_landmarker.task",point_size=5,line_thickness=2):"""加载姿势、手部、人脸三个模型"""base_pose = python.BaseOptions(model_asset_path=pose_model)base_hand = python.BaseOptions(model_asset_path=hand_model)base_face = python.BaseOptions(model_asset_path=face_model)self.pose_detector = vision.PoseLandmarker.create_from_options(vision.PoseLandmarkerOptions(base_options=base_pose,num_poses=1,running_mode=vision.RunningMode.IMAGE))self.hand_detector = vision.HandLandmarker.create_from_options(vision.HandLandmarkerOptions(base_options=base_hand,num_hands=2,running_mode=vision.RunningMode.IMAGE))self.face_detector = vision.FaceLandmarker.create_from_options(vision.FaceLandmarkerOptions(base_options=base_face,running_mode=vision.RunningMode.IMAGE))# 绘图参数self.point_size = point_sizeself.line_thickness = line_thicknessself.pose_connections = solutions.pose.POSE_CONNECTIONSself.hand_connections = solutions.hands.HAND_CONNECTIONSdef _draw_landmarks(self, frame, landmarks, connections=None, color=(0, 255, 0)):"""通用绘制函数"""h, w, _ = frame.shapefor lm in landmarks:cx, cy = int(lm.x * w), int(lm.y * h)cv2.circle(frame, (cx, cy), self.point_size, color, -1)if connections:for start, end in connections:x1, y1 = int(landmarks[start].x * w), int(landmarks[start].y * h)x2, y2 = int(landmarks[end].x * w), int(landmarks[end].y * h)cv2.line(frame, (x1, y1), (x2, y2), color, self.line_thickness)def do(self, frame,device):"""三模型检测 + 三屏展示"""if frame is None:return Nonemp_image = mp.Image(image_format=mp.ImageFormat.SRGB,data=cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))# 检测pose_res = self.pose_detector.detect(mp_image)hand_res = self.hand_detector.detect(mp_image)face_res = self.face_detector.detect(mp_image)skeleton_only = np.zeros_like(frame)skeleton_overlay = frame.copy()# 姿态绘制if pose_res.pose_landmarks:for pose_landmarks in pose_res.pose_landmarks:self._draw_landmarks(skeleton_only, pose_landmarks,self.pose_connections, (255, 255, 255))self._draw_landmarks(skeleton_overlay, pose_landmarks,self.pose_connections, (255, 255, 255))# 手部绘制if hand_res.hand_landmarks:for hand_landmarks in hand_res.hand_landmarks:self._draw_landmarks(skeleton_only, hand_landmarks,self.hand_connections, (0, 255, 255))self._draw_landmarks(skeleton_overlay, hand_landmarks,self.hand_connections, (0, 255, 255))# 人脸绘制(只画点,避免太密集)if face_res.face_landmarks:for face_landmarks in face_res.face_landmarks:self._draw_landmarks(skeleton_only, face_landmarks, None, (0, 0, 255))self._draw_landmarks(skeleton_overlay, face_landmarks, None, (0, 0, 255))# 拼接三屏triple_frame = np.concatenate([frame, skeleton_only, skeleton_overlay], axis=1)return triple_frame
这种可视化方式非常适合:
-
模型调试:对比原始图像与检测结果;
-
效果展示:直观展示算法检测效果;
-
数据采集:骨架单独图像可用于后续训练。
八、应用场景
-
智能健身
-
检测用户姿态是否正确;
-
对比标准动作与实际动作;
-
实时反馈给用户。
-
-
人机交互
-
通过手势实现自然交互;
-
表情捕捉用于虚拟角色驱动。
-
-
虚拟现实与元宇宙
-
捕捉全身骨骼与面部表情;
-
驱动虚拟形象进行动作和情感表达。
-
-
医疗康复
-
姿势检测用于康复训练指导;
-
手势与表情用于病患康复进度跟踪。
-
对 PiscTrace or PiscCode感兴趣?更多精彩内容请移步官网看看~🔗 PiscTrace