基于 mediapipe 做实时手部追踪

开发
在本文中,我将向你展示如何使用Python和网络摄像头轻松开始手部追踪算法,所有操作都在你的计算机本地运行。我们将直接使用mediapipe手部追踪解决方案,并了解其基本工作原理。

随着越来越多的资源和框架针对各种任务进行定制,开始计算机视觉应用从未如此简单。其中一个任务就是手部追踪,它在虚拟现实、手语翻译以及许多其他人机交互相关应用中有着广泛的用途。在本文中,我将向你展示如何使用Python和网络摄像头轻松开始手部追踪算法,所有操作都在你的计算机本地运行。我们将直接使用mediapipe手部追踪解决方案,并了解其基本工作原理。

项目设置

首先创建一个空的项目目录。我强烈建议你使用虚拟环境管理器,例如Miniconda,以分离不同的Python项目。我喜欢通过在项目目录中创建本地环境来设置我的环境,以避免弄乱我的全局Conda环境。

conda create -p ./env python=3.12 
conda activate ./env

安装Mediapipe

接下来我们需要安装mediapipe pip包。这非常简单,它会自动安装所有所需的依赖项。

pip install mediapipe

代码

现在我们可以开始创建一个main.py文件。首先导入所需的包,我们将使用opencv-python进行网络摄像头视频帧捕获,以及mediapipe手部解决方案及其绘图工具。

import cv2
import mediapipe.python.solutions.hands as mp_hands
import mediapipe.python.solutions.drawing_utils as mp_drawing
import mediapipe.python.solutions.drawing_styles as mp_drawing_styles

接下来我们需要设置网络摄像头的VideoCapture。通过指定索引0,我们获取第一个可用的网络摄像头。

cap = cv2.VideoCapture(index=0)

现在我们需要创建一个手部追踪对象。通过使用with语句,我们在帧捕获循环周围创建一个上下文,以便可以使用hands对象。这确保在with语句的上下文结束时,所有与追踪相关的资源都能正确清理。

with mp_hands.Hands(
    model_complexity=0,
    max_num_hands=2,
    min_detection_confidence=0.5,
    min_tracking_confidence=0.5,
) as hands:
  # TODO: video Frame loop

这里我们有几个配置选项。model_complexity定义是使用简单模型(0)还是更复杂的模型(1)。复杂模型在检测中通常具有更高的准确性,但会牺牲延迟。max_num_hands指定将检测到的手部数量的上限,例如,如果我们只想识别一只手,可以将其降低到1。min_detection_confidence和min_tracking_confidence分别指模型在首次检测手部时以及在保持追踪时的置信度。

为了创建视频帧循环,我们使用一个while循环,只要视频捕获打开,它就会运行。我们从视频捕获中读取最新的帧,如果成功,我们将其显示出来。请注意,我们水平翻转图像以获得类似镜子/自拍的效果。我们还会检查每一帧是否按下了键q,然后退出循环。最后在循环结束后,我们通过释放视频捕获资源来清理它。

with mp_hands.Hands(
    model_complexity=0,
    max_num_hands=2,
    min_detection_confidence=0.5,
    min_tracking_confidence=0.5,
) as hands:
    while cap.isOpened():
        success, frame = cap.read()
        if not success:
            print("Ignoring empty camera frame...")
            continue

        # TODO: check frame for hands
        # TODO: draw detected hand landmarks on frame

        cv2.imshow("Hand Tracking", cv2.flip(frame, 1))
        if cv2.waitKey(1) & 0xFF == ord("q"):
            break

cap.release()

现在唯一剩下要做的就是实现手部关键点检测及其可视化。唯一需要考虑的是,OpenCV以BGR(蓝、绿、红颜色通道顺序)格式加载图像,而模型是在RGB上训练的,因此为了获得最佳结果,我们也应该将帧转换为RGB。

注意:你也可以尝试在不转换为RGB的情况下运行检测。在我的情况下,它仍然有效,但检测的准确性要低得多。

# Check the frame for hands
frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
results = hands.process(frame_rgb)

为了检查这是否有效,我们可以在检测到手部时添加一个打印语句:

if results.multi_hand_landmarks is None:
    print("No hands detected")
else:
    print(f"Number of hands detected: {len(results.multi_hand_landmarks)}")

最后,我们可以使用mediapipe提供的绘图工具在帧上注释,以可视化帧中的手部。通过指定HAND_CONNECTIONS常量,手部关键点之间的连接以及关键点本身将被绘制出来。此外,指定的默认绘图规范允许对不同手指进行明显的着色。

# Draw the hand annotations on the image
if results.multi_hand_landmarks:
    for hand_landmarks in results.multi_hand_landmarks:
        mp_drawing.draw_landmarks(
            image=frame,
            landmark_list=hand_landmarks,
            connections=mp_hands.HAND_CONNECTIONS,
            landmark_drawing_spec=mp_drawing_styles.get_default_hand_landmarks_style(),
            connection_drawing_spec=mp_drawing_styles.get_default_hand_connections_style(),
        )

mediapipe 工作原理

手部追踪的架构主要由两个阶段组成,一个是手掌检测,粗略地检测手部的位置,然后是手部关键点检测,更精确地定位手部和手指的不同部分。

第一阶段的手掌检测模型基于SSD。因此,该模型将完整图像的像素值作为输入,并输出描述图像中手掌可能位置的边界框以及每个框的置信度分数。这里使用了一些技巧,例如将锚框(在网络中创建的分类前的提议)限制为正方形图像。

第二部分,手部关键点模型,是一个回归模型,它将手掌检测的边界框中的裁剪图像作为输入,并返回手部所有21个关键点的3D坐标。

参考资料:

  • mediapipe解决方案:https://mediapipe.readthedocs.io/en/latest/solutions/hands.html
  • SSD论文:https://arxiv.org/abs/1512.02325
  • 完整代码:https://github.com/trflorian/hand-tracker
责任编辑:赵宁宁 来源: 小白玩转Python
相关推荐

2019-08-22 10:48:56

谷歌开源开发者

2024-03-11 16:33:26

机器狗训练

2015-10-09 13:42:26

hbase实时计算

2023-10-16 23:43:52

云原生可观测性

2022-07-29 09:35:25

WAF溯源识别

2010-03-12 15:07:08

2024-04-26 08:00:00

开源人体姿势跟踪

2015-01-21 09:47:59

2024-04-09 10:02:13

Spring数据Redis

2019-08-21 20:08:34

人工智能手势识别谷歌

2022-01-24 16:06:58

Linux 5.17RTLA工具

2014-03-25 14:21:18

WebSocket实时

2024-09-04 15:42:38

OpenCV开发Python

2022-03-03 12:24:17

暗码追踪数字水印打印机

2024-12-24 07:00:00

MediaPipe面部识别

2017-04-06 22:40:52

数据分析追踪系统微信

2021-07-13 07:04:19

Flink数仓数据

2018-09-19 10:01:39

MSSQL列存储实时分析

2021-03-22 11:10:09

Redis架构MQ

2013-07-30 10:29:07

SUSE LinuxNFS
点赞
收藏

51CTO技术栈公众号