PiscCode基于 Mediapipe 的人体多模态关键点检测与可视化系统 —— HumanMultiLandmarker 深度解析
PiscC基于Google Mediapipe Tasks API的HumanMultiLandmarker类,这是一个融合人体姿势、手部和面部关键点检测的多模态系统。该系统通过三个预训练模型(PoseLandmarker、HandLandmarker、FaceLandmarker)实现33个全身关键点、21个手部关键点和478个面部关键点的实时检测,并采用三屏对比方式展示原始画面、骨架点线图和骨
一、引言
在计算机视觉领域,人体关键点检测(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.shape
for 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 vision
class 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_size
self.line_thickness = line_thickness
self.pose_connections = solutions.pose.POSE_CONNECTIONS
self.hand_connections = solutions.hands.HAND_CONNECTIONS
def _draw_landmarks(self, frame, landmarks, connections=None, color=(0, 255, 0)):
"""通用绘制函数"""
h, w, _ = frame.shape
for 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 None
mp_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
更多推荐





所有评论(0)