PiscCode基于 Mediapipe 的人体多模态关键点检测与可视化系统 —— HumanMultiLandmarker 深度解析

一、引言

在计算机视觉领域,人体关键点检测(Human Pose Estimation,HPE)一直是研究和应用的热点方向之一。随着深度学习与实时图像处理技术的发展,人体姿势估计已经从传统的 2D 检测走向了 3D 空间建模,并在 运动分析、动作识别、虚拟现实、游戏交互、医疗康复、智能健身 等众多场景中得到了广泛应用。

然而,仅仅检测人体骨架往往无法满足实际需求。人机交互过程中,手部动作面部表情同样具有重要意义:

  • 手势识别 可以实现更自然的人机控制,例如手势控制智能家居、无人机;

  • 人脸关键点检测 则是表情识别、虚拟形象驱动、情感计算的重要基础;

  • 姿势检测 则是全身动态捕捉、运动姿态评估的核心。

因此,一个融合 姿势(Pose)、手部(Hand)、人脸(Face) 三大关键点检测任务的多模态分析系统,不仅能提供更完整的人体建模,还能大幅提升交互体验。

本文将详细解析基于 Google Mediapipe Tasks API 封装的 HumanMultiLandmarker 类。它能够同时调用三个模型:人体骨架检测、手部关键点检测、人脸关键点检测,并在同一张画面上输出三种结果。同时,它还能将结果组织成三屏对比图(原始画面 / 骨架点线图 / 骨架叠加图),帮助开发者更直观地理解和调试模型效果。


二、技术背景

2.1 Mediapipe 简介

Mediapipe 是 Google 开源的一套跨平台、可扩展的机器学习应用框架,专注于 实时多模态感知。其核心优势在于:

  1. 丰富的预训练模型:包含人脸检测、手部跟踪、姿势估计、物体检测等;

  2. 跨平台支持:支持 Android、iOS、Web、Python、C++ 等;

  3. 高效实时性能:能够在 CPU、GPU 上流畅运行;

  4. 可组合性强:多个模块可以像“积木”一样拼装组合。

其中,人体相关的关键模型包括:

  • 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.circlecv2.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()

系统生成三张图像:

  1. 原始图像(未修改);

  2. 骨架图像(黑底,只绘制点和线);

  3. 叠加图像(原始帧上绘制骨架)。

检测过程:

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

这种可视化方式非常适合:

  1. 模型调试:对比原始图像与检测结果;

  2. 效果展示:直观展示算法检测效果;

  3. 数据采集:骨架单独图像可用于后续训练。


八、应用场景

  1. 智能健身

    • 检测用户姿态是否正确;

    • 对比标准动作与实际动作;

    • 实时反馈给用户。

  2. 人机交互

    • 通过手势实现自然交互;

    • 表情捕捉用于虚拟角色驱动。

  3. 虚拟现实与元宇宙

    • 捕捉全身骨骼与面部表情;

    • 驱动虚拟形象进行动作和情感表达。

  4. 医疗康复

    • 姿势检测用于康复训练指导;

    • 手势与表情用于病患康复进度跟踪。

   对 PiscTrace or PiscCode感兴趣?更多精彩内容请移步官网看看~🔗 PiscTrace

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/94269.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/94269.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

文献阅读笔记【物理信息机器学习】:Physics-informed machine learning

文献阅读笔记:Physics-informed machine learningSummaryResearch ObjectiveBackground / Problem Statement问题背景研究现状需解决的问题问题出现的原因分析问题解决思路Method(s)问题建模作者解决问题的方法/算法1. 观测偏差(Observational Biases&am…

Linux服务环境搭建指南

实验拓扑概述**实验拓扑: APPSRV: 主机名:appsrv.example.com ip地址:192.168.100.10 网关:192.168.100.254 网卡为NAT模式 STORAGESRV: 主机名:storagesrv.example.com ip地址:192.…

[特殊字符] 数据库知识点总结(SQL Server 方向)

一、数据库基础概念数据库(Database):存储和管理数据的容器。数据表(Table):以行和列形式组织数据。行(Row):一条记录。列(Column):字…

【PSINS工具箱】MATLAB例程,二维平面上的组合导航,EKF融合速度、位置和IMU数据,4维观测量

文章目录关于工具箱程序简介代码概述核心功能与步骤运行结果MATLAB代码关于工具箱 本文所述的代码需要基于PSINS工具箱,工具箱的讲解: PSINS初学指导:https://blog.csdn.net/callmeup/article/details/137087932 本文为二维平面上的定位&am…

MiMo-VL 技术报告

摘要 我们开源了 MiMo-VL-7B-SFT 和 MiMo-VL-7B-RL 两个强大的视觉语言模型,它们在通用视觉理解和多模态推理方面均展现出最先进的性能。MiMo-VL-7B-RL 在 40 项评估任务中的 35 项上优于 Qwen2.5-VL-7B,并在 OlympiadBench 上获得 59.4 分,超越了参数量高达 780 亿的模型。…

CTFshow Pwn入门 - pwn 19

先看main函数:fclose(_bss_start) fclose(stdout) 关闭了默认fd1的输出,所以system的结果无法直接看到。 思路: 输出重定向。 ls 1>&0 ls >&0 ls >&2 ###三种写法均可将输出重定向到能回显的终端并获得一个新的交互…

Redis(以Django为例,含具体操作步骤)

简介Redis(Remote Dictionary Server)是一个开源的内存数据结构存储系统,支持多种数据结构(如字符串、哈希、列表、集合、有序集合等),可用作数据库、缓存或消息队列。其核心特点包括:高性能&am…

浏览器解析网址的过程

问题浏览器解析网址的过程我的回答当你在浏览器地址栏输入一个URL(比如www.example.com)并按下回车后,会发生以下一系列步骤:首先,浏览器会解析URL结构,确定要访问的协议、域名和路径。如果你没有输入协议部…

NVIDIA Nsight Systems性能分析工具

* 性能分析 NVIDIA Nsight Systems (推荐): 这是 NVIDIA 官方推荐的更现代、功能更强大的分析工具。 安装 Nsight Systems在 Docker 容器中启动程序:# 确保你在启动容器时挂载了/usr/local/cuda/targets/x86_64-linux/lib/ 和 /usr/local/nvidia/lib64 #…

后台管理系统-14-vue3之tag标签页的实现

文章目录 1 tag静态实现 1.1 CommonTag.vue(el-tag) 1.2 Main.vue(普通组件标签) 2 tag通过pinia管理 2.1 CommonAside.vue(菜单点击事件) 2.2 stores/index.js(selectMenu()和tags) 2.3 CommonTag.vue(计算属性tags) 3 点击tag之后跳转到指定页面 3.1 views/Mail.vue(商品) 3.…

CMake2: CMakeLists.txt的常用命令

参考链接: 爱编程的大丙 | CMake教程 CMakeLists指令以及常用方法 现代 CMake 教程 文章目录1. cmake_minimum_required( )2. project( )3. add_executable( )4. set()5. aux_source_directory( )6. file( )7. include_directories( )8. add_library( )9. link_libraries()与li…

Ansible入门:自动化运维基础

Ansible 基础概念与安装1. 自动化动机 (Motivation for Automation)概念解释: 指为什么要用Ansible等工具来替代手动管理服务器。核心动机包括:效率与速度: 同时在上百甚至上千台服务器上执行任务,秒级完成,远非人工可…

【测试】基于博客系统的测试报告

前言 本篇博客对简易的博客系统做的测试总结一份测试报告,包含功能测试,自动化测试,性能测试 💓 个人主页:zkf ⏩ 文章专栏:测试 若有问题 评论区见📝 🎉欢迎大家点赞👍…

Oracle:配置让插入语句时id自动输入

Oracle:配置让插入语句时id自动输入无需手动指定,核心是利用 序列(Sequence) 或 自增列(Identity Column) 来自动生成唯一值。以下是两种常用方案:方案 1:使用序列(Sequence&#xf…

秒杀服务的回调方案

在秒杀场景中,用户点击“抢购”后,后端需要通过异步处理应对高并发(避免请求阻塞),同时需通过实时回调机制将最终结果(成功/失败)推送给客户端并展示。核心方案是:“前端发起请求→后…

php apache无法接收到Authorization header

Apache 默认不传递 Authorization头到后端环境(如 PHP)。其表现是:print_r($_SERVER)时, 没有 [Authorization] :Array ([Accept-Language] > zh,en;q0.9,zh-CN;q0.8,en-US;q0.7[Accept-Encoding] > gzip, defla…

当我们想用GPU(nlp模型篇)

在个人设备上“把 GPU 真正用起来”做 NLP,分五步:准备 → 安装 → 验证 → 训练/推理 → 踩坑排查。下面每一步都给出可复制命令和常见错误。 ────────────────── 1. 硬件准备 • 一张 NVIDIA GPU,算力 ≥ 6.1&#xff08…

CryptSIPVerifyIndirectData函数分析

可以使用此函数从SIP接口对应的文件中提取签名信息 CryptSIPVerifyIndirectData:将当前文件的哈希结果做为“指纹”,并与从CryptSIPGetSignedDataMsg中提取的签名信息进行比较。 如果哈希结果相同,则意味着当前文件与之前签名的文件相同&…

20250823解决荣品RD-RK3588-MID开发板在充电的时候大概每10s屏幕会像水波纹闪烁一下

20250823解决荣品RD-RK3588-MID开发板在充电的时候大概每10s屏幕会像水波纹闪烁一下 2025/8/23 17:58【结论】:使用直流电源供电,给电池【快速】充电,但是直流电源的电压稳定,电流抖动导致的!那个是2.4G 已经知道了我司…

CANN安装

前提条件 请参考本文档正确安装和使用CANN软件,不建议将CANN安装在共享磁盘后,通过挂载的方式使用CANN,因为CANN对文件系统有文件锁的依赖,部分共享存储不支持文件锁,可能导致任务拉起失败。 root用户和非root用户安装CANN软件包的步骤一致,当前示例步骤以非root用户为例…