使用 MediaPipe 实现实时手部追踪和手势识别 | Rerun展示

点击下方卡片,关注“小白玩转Python”公众号

在本文中,我将展示一个使用 MediaPipe Python 和 Rerun SDK 进行手部追踪和手势识别的示例。如果您有兴趣深入了解并扩展您的知识,我将指导您如何安装 MediaPipe Python 和 Rerun SDK 来进行手部追踪、识别不同手势并可视化数据。因此,您将学习到:

  • 如何安装 MediaPipe Python 和 Rerun

  • 如何使用 MediaPipe 进行手部追踪和手势识别

  • 如何在 Rerun Viewer 中可视化手部追踪和手势识别的结果


手部追踪和手势识别技术

在开始之前,让我们感谢使这一技术成为可能的科技。手部追踪和手势识别技术旨在使设备能够将手部动作和手势解释为命令或输入。这项技术的核心是一个预训练的机器学习模型,它分析视觉输入并识别手部标志和手势。这种技术的实际应用非常广泛,因为手部动作和手势可以用于控制智能设备。人机交互、机器人技术、游戏和增强现实是该技术最有前途的应用领域之一。

然而,我们应始终注意如何使用这项技术。在敏感和关键系统中使用它非常具有挑战性,因为模型可能会误解手势,并且产生误报的可能性并不小。利用这项技术会带来伦理和法律挑战,因为用户可能不希望他们的手势在公共场所被记录。如果您打算在实际场景中实现这项技术,务必要考虑任何伦理和法律问题。

先决条件与设置

首先,您需要安装必要的库,包括 OpenCV、MediaPipe 和 Rerun。MediaPipe Python 是一个方便的工具,适合开发者在设备上集成计算机视觉和机器学习解决方案,而 Rerun 是一个可视化随时间变化的多模态数据的 SDK。

# Install the required Python packages specified in the requirements file
pip install -r examples/python/gesture_detection/requirements.txt

然后,您需要从这里下载预定义模型:HandGestureClassifier。

使用 MediaPipe 进行手部追踪和手势识别

05b935717d05652109037dcd9f273aa5.png

根据 Google 的手势识别任务指南:“MediaPipe 手势识别任务可以让您实时识别手势,并提供识别的手势结果以及检测到的手部标志。您可以使用此任务从用户那里识别特定手势,并调用与这些手势对应的应用程序功能。”

现在,让我们尝试使用 MediaPipe 预训练模型进行手势识别的示例图像。总体来说,下面的代码为初始化和配置 MediaPipe 手势识别解决方案奠定了基础。

from mediapipe.tasks.python import vision
from mediapipe.tasks import pythonclass GestureDetectorLogger:def __init__(self, video_mode: bool = False):self._video_mode = video_modebase_options = python.BaseOptions(model_asset_path='gesture_recognizer.task')options = vision.GestureRecognizerOptions(base_options=base_options,running_mode=mp.tasks.vision.RunningMode.VIDEO if self._video_mode else mp.tasks.vision.RunningMode.IMAGE)self.recognizer = vision.GestureRecognizer.create_from_options(options)def detect(self, image: npt.NDArray[np.uint8]) -> None:image = mp.Image(image_format=mp.ImageFormat.SRGB, data=image)# Get results from Gesture Detection modelrecognition_result = self.recognizer.recognize(image)for i, gesture in enumerate(recognition_result.gestures):# Get the top gesture from the recognition resultprint("Top Gesture Result: ", gesture[0].category_name)if recognition_result.hand_landmarks:# Obtain hand landmarks from MediaPipehand_landmarks = recognition_result.hand_landmarksprint("Hand Landmarks: " + str(hand_landmarks))# Obtain hand connections from MediaPipemp_hands_connections = mp.solutions.hands.HAND_CONNECTIONSprint("Hand Connections: " + str(mp_hands_connections))

GestureDetectorLogger 类中的 detect 函数接受一张图片作为其参数,并打印出模型的结果,突出显示识别出的顶部手势和检测到的手部标志点。有关模型的更多详细信息,请参考其模型卡。

您可以使用以下代码自行尝试:

def run_from_sample_image(path)-> None:image = cv2.imread(str(path))show_image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)logger = GestureDetectorLogger(video_mode=False)logger.detect_and_log(show_image)# Run the gesture recognition on a sample image
run_from_sample_image(SAMPLE_IMAGE_PATH)


使用 Rerun 进行验证、调试和演示

这一步允许您确保解决方案的可靠性和有效性。现在模型已经准备好,可以可视化结果以验证准确性、调试潜在问题,并展示其功能。使用 Rerun SDK 可视化结果既简单又快速。

如何使用 Rerun?

  1. 使用 Rerun SDK 从代码中记录多模态数据流

  2. 可视化并与本地或远程的实时或录制的流进行交互

  3. 交互式构建布局和自定义可视化

  4. 在需要时扩展 Rerun

在编写代码之前,您应该访问安装 Rerun Viewer 页面以安装 Viewer。然后,我强烈建议通过阅读 Python 快速入门和在 Python 中记录数据的指南来熟悉 Rerun SDK。这些初始步骤将确保设置顺利,并帮助您开始即将进行的代码实现。

从视频或实时运行

对于视频流,我们使用 OpenCV。您可以选择特定视频的文件路径,或通过提供参数 0 或 1 访问自己的摄像头(使用 0 表示默认摄像头;在 Mac 上,您可能需要使用 1)。

特别要强调的是时间线的引入。Rerun 时间线功能使得能够将数据与一个或多个时间线相关联。因此,视频的每一帧都与其对应的时间戳相关联。

def run_from_video_capture(vid: int | str, max_frame_count: int | None) -> None:"""Run the detector on a video stream.Parameters----------vid:The video stream to run the detector on. Use 0/1 for the default camera or a path to a video file.max_frame_count:The maximum number of frames to process. If None, process all frames."""cap = cv2.VideoCapture(vid)fps = cap.get(cv2.CAP_PROP_FPS)detector = GestureDetectorLogger(video_mode=True)try:it: Iterable[int] = itertools.count() if max_frame_count is None else range(max_frame_count)for frame_idx in tqdm.tqdm(it, desc="Processing frames"):ret, frame = cap.read()if not ret:breakif np.all(frame == 0):continueframe_time_nano = int(cap.get(cv2.CAP_PROP_POS_MSEC) * 1e6)if frame_time_nano == 0:frame_time_nano = int(frame_idx * 1000 / fps * 1e6)frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)rr.set_time_sequence("frame_nr", frame_idx)rr.set_time_nanos("frame_time", frame_time_nano)detector.detect_and_log(frame, frame_time_nano)rr.log("Media/Video",rr.Image(frame))except KeyboardInterrupt:passcap.release()cv2.destroyAllWindows()

记录数据进行可视化

ccaa7dab95ccf81a9b9ee20183252177.png

在 Rerun Viewer 中可视化数据,使用 Rerun SDK 记录数据至关重要。之前提到的指南提供了这个过程的见解。在这种情况下,我们提取手部标志点作为规范化值,然后使用图像的宽度和高度将其转换为图像坐标。这些坐标随后作为 2D 点记录到 Rerun SDK 中。此外,我们识别标志点之间的连接,并将它们作为 2D 线段记录。

对于手势识别,结果会打印到控制台。然而,在源代码中,您可以探索一种使用 TextDocument 和表情符号将这些结果呈现给查看器的方法。

class GestureDetectorLogger:def detect_and_log(self, image: npt.NDArray[np.uint8], frame_time_nano: int | None) -> None:# Recognize gestures in the imageheight, width, _ = image.shapeimage = mp.Image(image_format=mp.ImageFormat.SRGB, data=image)recognition_result = (self.recognizer.recognize_for_video(image, int(frame_time_nano / 1e6))if self._video_modeelse self.recognizer.recognize(image))# Clear the valuesfor log_key in ["Media/Points", "Media/Connections"]:rr.log(log_key, rr.Clear(recursive=True))for i, gesture in enumerate(recognition_result.gestures):# Get the top gesture from the recognition resultgesture_category = gesture[0].category_name if recognition_result.gestures else "None"print("Gesture Category: ", gesture_category) # Log the detected gestureif recognition_result.hand_landmarks:hand_landmarks = recognition_result.hand_landmarks# Convert normalized coordinates to image coordinatespoints = self.convert_landmarks_to_image_coordinates(hand_landmarks, width, height)# Log points to the image and Hand Entityrr.log("Media/Points",rr.Points2D(points, radii=10, colors=[255, 0, 0]))# Obtain hand connections from MediaPipemp_hands_connections = mp.solutions.hands.HAND_CONNECTIONSpoints1 = [points[connection[0]] for connection in mp_hands_connections]points2 = [points[connection[1]] for connection in mp_hands_connections]# Log connections to the image and Hand Entity rr.log("Media/Connections",rr.LineStrips2D(np.stack((points1, points2), axis=1),colors=[255, 165, 0]))def convert_landmarks_to_image_coordinates(hand_landmarks, width, height):return [(int(lm.x * width), int(lm.y * height)) for hand_landmark in hand_landmarks for lm in hand_landmark]


3D 点

最后,我们检查如何将手部标志呈现为 3D 点。我们首先在 init 函数中使用 Annotation Context 定义点之间的连接,然后将它们记录为 3D 点。

class GestureDetectorLogger:
–def __init__(self, video_mode: bool = False):# ... existing code ...rr.log("/",rr.AnnotationContext(rr.ClassDescription(info=rr.AnnotationInfo(id=0, label="Hand3D"),keypoint_connections=mp.solutions.hands.HAND_CONNECTIONS)),timeless=True,)rr.log("Hand3D", rr.ViewCoordinates.RIGHT_HAND_X_DOWN, timeless=True)def detect_and_log(self, image: npt.NDArray[np.uint8], frame_time_nano: int | None) -> None:# ... existing code ...if recognition_result.hand_landmarks:hand_landmarks = recognition_result.hand_landmarkslandmark_positions_3d = self.convert_landmarks_to_3d(hand_landmarks)if landmark_positions_3d is not None:rr.log("Hand3D/Points",rr.Points3D(landmark_positions_3d, radii=20, class_ids=0, keypoint_ids=[i for i in range(len(landmark_positions_3d))]),)# ... existing code ...

详细代码可以参考:https://github.com/rerun-io/rerun

·  END  ·

HAPPY LIFE

db1829df6e622c882be54077c5554486.png

本文仅供学习交流使用,如有侵权请联系作者删除

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

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

相关文章

Linux部署SVN

一.下载与安装 (1)yum安装 yum install subversion (2)源文件编译安装 ①下载svn源文件 subversion-xxx.tar.gz(subversion 源文件) subversion-deps-xxx.tar.gz(subversion依赖文件&…

项目四 OpenStack身份管理

任务一 理解身份服务 1.1 •Keystone的基本概念 • 认证 ( Authentication ) —— 确认用户身份的过程 ,又称身份验证 。 • 凭证 ( Credentials ) —— 又 称凭据,是用于 确认用户身份的数据 。 • 令牌…

短视频最佳时长:成都柏煜文化传媒有限公司

探索时间与内容之间的完美平衡 成都柏煜文化传媒有限公司 在数字媒体日益繁荣的今天,短视频已成为人们获取信息、娱乐休闲的重要形式。然而,关于短视频的最佳时长,一直是一个备受争议的话题。本文将探讨短视频时长的各种考量因素&#xff0…

MySQL报错Duplicate entry ‘0‘ for key ‘PRIMARY‘

报错现场 现象解释 因为你在插入时没有给 Customer.Id 赋值,MySQL 会倾向于赋值为 NULL。但是主键不能为 NULL,所以 MySQL 帮了你一个忙,将值转换为 0。这样,在第二次插入时就会出现冲突(如果已经有一条记录为 0&…

微服务——服务治理

目录 1 什么是服务治理?2 为什么需要服务治理?3 服务治理的关键点3.1 服务注册与发现3.2 负载均衡3.3 容错与熔断3.4 服务监控与告警3.5 服务配置管理 4 示例说明5 总结 1 什么是服务治理? 简单来说,服务治理就是对微服务架构中的…

iptables(11)target(SNAT、DNAT、MASQUERADE、REDIRECT)

简介 前面我们已经介绍了ACCEPT、DROP、REJECT、LOG,这篇文章我们介绍SNAT、DNAT、MASQUERADE、REDIRECT,这几个参数的定义我们在上篇文章中都有介绍,我这里再列出回顾一下 DNAT(目标地址转换)和 SNAT(源地址转换) 原理:修改数据包的源或目标 IP 地址。通常用于 NAT(…

小迪安全v2023笔记 1-18

小迪安全v2023笔记 1-18 棱角社区 文章目录 1. 基础入门1. 正向shell与反向shell2. web应用3. 抓包,封包,协议,app,小程序,pc应用,web应用 2. 信息打点1. 常见信息获取2. 文件泄露3. 常见阻碍4. CDN绕过&a…

Stable Diffusion——SDXL 1.0原理解析

1. SDXL 1.0 简介 SDXL 1.0是Stability AI推出的新基础模型,作为Stable Diffusion的大幅改进版本,它是一个用于文本到图像合成的潜在扩散模型(LDM)。作为Stable Diffusion的最新进化,它正在超越其前身,并与…

录制视频怎么操作?手把手教会你!

在这个互联网科技高速发展的时代,录制视频已经成为了人们生活中一个不可或缺的技能。无论是记录游戏精彩瞬间、制作教程、分享生活趣事,还是进行在线教学,录制视频都是一种非常直观有效的方式。可是录制视频怎么操作呢?本文将介绍…

算法学习笔记——单双链表及其反转—堆栈诠释

单双链表及其反转——堆栈诠释 按值传递 int、long、byte、short、char、float、double、boolean和String 都是按值传递 概念:在方法被调用时,实参通过形参把它的内容副本传入方法内部,此时形参接收到的内容是实参值的一个拷贝,…

dbeaver数据库链接工具

1、下载dbeaver 一个绿色版一个安装版,官网开源版 2、安装 3、可以导入之前navicat的链接 导入 选择navicat 反编译密码的:https://tool.lu/coderunner navicat 版本15的密码解密:https://www.iatodo.com/navicatpw

服务运营 | MS文章精选:线上点单,当真免排队?餐饮零售与医疗场景中的全渠道运营

编者按: 小A走进了一家奶茶店,准备向店员点单,但却在屏幕上看到还有98杯奶茶待制作(因为线上订单突然暴增)。因此,小A不满地嘟囔着离开了奶茶店。这个例子展示了线上渠道可能会对线下渠道造成一些负面影响…

使用AES,前端加密,后端解密,spring工具类了

学习python的时候,看到很多会对参数进行加密,于是好奇心驱使下,让我去了解了下AES加密如何在java中实现。 首先 npm install crypto-js 然后在你的方法中,给你们前端源码看看,因为我用的ruoyi框架做的实验&#xff…

四川音盛佳云电子商务有限公司抖音电商的先行者

在当今数字时代,电商行业风起云涌,各大平台竞相争夺市场份额。而在这其中,四川音盛佳云电子商务有限公司以其独特的抖音电商服务模式,悄然崛起,成为了行业中的一股不可忽视的力量。今天,就让我们一起走进音…

【GD32F303红枫派使用手册】第二十六节 EXMC-液晶驱动实验

26.1 实验内容 通过本实验主要学习以下内容: LCD显示原理 EXMC NOR/SRAM模式时序和8080并口时序 LCD显示控制 26.2 实验原理 使用MCU的EXMC外设实现8080并口时序,和TFT-LCD控制器进行通信,控制LCD显示图片、字符、色块等。 26.2.1 TFT…

图像超分辨率重建

一、什么是图像超分辨 图像超分辨是一种技术,旨在通过硬件或软件的方法提高原有图像的分辨率。这一过程涉及从一系列低分辨率的图像中获取一幅高分辨率的图像,实现了时间分辨率向空间分辨率的转换。超分辨率重建的核心思想是利用多帧图像序列的时间带宽来…

计算机毕业设计Thinkphp/Laravel学生考勤管理系统zyoqy

管理员登录学生考勤管理系统后,可以对首页、个人中心、公告信息管理、年级管理、专业管理、班级管理、学生管理、教师管理、课程信息管理、学生选课管理、课程签到管理、请假申请管理、销假申请管理等功能进行相应操作,如图5-2所示。学生登录进入学生考勤…

【Spine学习16】之 人物面部绑定

1、创建头部骨骼 一根头骨 以头骨为父结点创建一个面部控制器face-holder 2、创建头发和face面部控制结点的变换约束 左右头发的约束指向为face结点 3、设定后发的变换约束,约束指向为face结点,反方向移动 设置参数为-100 同理,耳朵也依…

【Python时序预测系列】基于CNN+Bi-LSTM实现单变量时间序列预测(案例+源码)

这是我的第309篇原创文章。 一、引言 基于CNN(卷积神经网络)和Bi-LSTM(双向长短期记忆网络)的单变量时间序列预测是一种结合空间特征提取和时间依赖建模的方法。以下是一个基于Python和TensorFlow/Keras实现的示例,展…

YOLOv8改进 | 主干网络| 可变形卷积网络C2f_DCN【CVPR2017】

💡💡💡本专栏所有程序均经过测试,可成功执行💡💡💡 专栏目录:《YOLOv8改进有效涨点》专栏介绍 & 专栏目录 | 目前已有40篇内容,内含各种Head检测头、损失函数Loss、B…