Python 手势识别指南

借助 MediaPipe 手势识别器任务,你可以实时识别手势; 提供识别出的手势结果以及检测到的手势 的双手。以下说明介绍了如何使用手势识别程序 Python 应用。

您可以通过查看网页 演示 功能、模型和配置选项 请参阅概览

代码示例

手势识别程序的示例代码提供了该手势的完整实现, 供您参考。此代码可帮助您测试此任务, 开始构建自己的手势识别器。您可以查看、运行 修改手势识别程序示例 代码 只需使用网络浏览器即可。

如果您要实现适用于 Raspberry Pi 的手势识别器,请参阅 Raspberry Pi 示例 app

设置

本部分介绍了设置开发环境和 一些专门用于使用手势识别器的代码项目。有关 设置开发环境以使用 MediaPipe 任务,包括 平台版本要求,请参阅适用于 Python

软件包

MediaPipe 手势识别器任务需要 mediapipe PyPI 软件包。你可以安装并 使用以下命令导入这些依赖项:

$ python -m pip install mediapipe

导入

导入以下类以使用手势识别器任务功能:

import mediapipe as mp
from mediapipe.tasks import python
from mediapipe.tasks.python import vision

型号

MediaPipe 手势识别器任务需要一个与 此任务。如需详细了解适用于手势识别程序且经过训练的模型, 请参阅任务概览的“模型”部分

选择并下载模型,然后将其存储在本地目录中:

model_path = '/absolute/path/to/gesture_recognizer.task'

在 Model Name 参数中指定模型的路径,如下所示:

base_options = BaseOptions(model_asset_path=model_path)

创建任务

MediaPipe 手势识别器任务使用 create_from_options 函数来设置 任务。create_from_options 函数接受配置值 处理选项如需详细了解配置选项,请参阅 配置选项

以下代码演示了如何构建和配置此任务。

这些示例还展示了图片任务构建的不同变体, 视频文件和直播视频流

映像

import mediapipe as mp

BaseOptions = mp.tasks.BaseOptions
GestureRecognizer = mp.tasks.vision.GestureRecognizer
GestureRecognizerOptions = mp.tasks.vision.GestureRecognizerOptions
VisionRunningMode = mp.tasks.vision.RunningMode

# Create a gesture recognizer instance with the image mode:
options = GestureRecognizerOptions(
    base_options=BaseOptions(model_asset_path='/path/to/model.task'),
    running_mode=VisionRunningMode.IMAGE)
with GestureRecognizer.create_from_options(options) as recognizer:
  # The detector is initialized. Use it here.
  # ...
    

视频

import mediapipe as mp

BaseOptions = mp.tasks.BaseOptions
GestureRecognizer = mp.tasks.vision.GestureRecognizer
GestureRecognizerOptions = mp.tasks.vision.GestureRecognizerOptions
VisionRunningMode = mp.tasks.vision.RunningMode

# Create a gesture recognizer instance with the video mode:
options = GestureRecognizerOptions(
    base_options=BaseOptions(model_asset_path='/path/to/model.task'),
    running_mode=VisionRunningMode.VIDEO)
with GestureRecognizer.create_from_options(options) as recognizer:
  # The detector is initialized. Use it here.
  # ...
    

直播

import mediapipe as mp

BaseOptions = mp.tasks.BaseOptions
GestureRecognizer = mp.tasks.vision.GestureRecognizer
GestureRecognizerOptions = mp.tasks.vision.GestureRecognizerOptions
GestureRecognizerResult = mp.tasks.vision.GestureRecognizerResult
VisionRunningMode = mp.tasks.vision.RunningMode

# Create a gesture recognizer instance with the live stream mode:
def print_result(result: GestureRecognizerResult, output_image: mp.Image, timestamp_ms: int):
    print('gesture recognition result: {}'.format(result))

options = GestureRecognizerOptions(
    base_options=BaseOptions(model_asset_path='/path/to/model.task'),
    running_mode=VisionRunningMode.LIVE_STREAM,
    result_callback=print_result)
with GestureRecognizer.create_from_options(options) as recognizer:
  # The detector is initialized. Use it here.
  # ...
    

配置选项

此任务具有以下适用于 Python 应用的配置选项:

选项名称 说明 值范围 默认值
running_mode 设置任务的运行模式。有三个 模式:

IMAGE:单图输入的模式。

VIDEO:视频已解码帧的模式。

LIVE_STREAM:输入流媒体直播模式 例如来自相机的数据。在此模式下,resultListener 必须为 调用以设置监听器以接收结果 异步执行。
{IMAGE, VIDEO, LIVE_STREAM} IMAGE
num_hands 最多能检测出手的数量 GestureRecognizer Any integer > 0 1
min_hand_detection_confidence 手部检测要计算的最低置信度分数 在手掌检测模型中被认为是成功的。 0.0 - 1.0 0.5
min_hand_presence_confidence 手部存在状态分数的最低置信度分数 特征点检测模型。在手势识别程序的视频模式和直播模式下, 如果来自手部特征码模型的手部存在信心得分低于 达到此阈值后,就会触发手掌检测模型。否则, 轻量级的手部跟踪算法用于确定 进行后续地标检测。 0.0 - 1.0 0.5
min_tracking_confidence 要考虑的手部跟踪的最低置信度分数 成功。这是两只手之间的边界框 IoU 阈值, 分别表示当前帧和最后一帧。处于视频模式和直播模式 手势识别程序,如果追踪失败,手势识别程序会触发手部 检测。否则,系统会跳过手部检测。 0.0 - 1.0 0.5
canned_gestures_classifier_options 用于配置预设手势分类器行为的选项。预设的手势为 ["None", "Closed_Fist", "Open_Palm", "Pointing_Up", "Thumb_Down", "Thumb_Up", "Victory", "ILoveYou"]
  • 显示名称语言区域:通过 TFLite 模型元数据指定的显示名称(如果有)的语言区域。
  • 结果数上限:要返回的评分最高的分类结果的数量上限。如果 <0,则返回所有可用的结果。
  • 分数阈值:低于此分数的结果将被拒绝。如果设置为 0,则返回所有可用的结果。
  • 类别许可名单:类别名称许可名单。如果为非空值,则类别不在此集合中的分类结果将被滤除。与拒绝名单相互排斥。
  • 类别拒绝名单:类别名称的拒绝名单。如果为非空值,则此集合中的类别将被滤除。与许可名单相互排斥。
    • 显示名称语言区域:any string
    • 结果数上限:any integer
    • 分数阈值:0.0-1.0
    • 类别许可名单:vector of strings
    • 类别拒绝名单:vector of strings
    • 显示名称语言区域:"en"
    • 结果数上限:-1
    • 分数阈值:0
    • 类别许可名单:空
    • 类别拒绝名单:空
    custom_gestures_classifier_options 用于配置自定义手势分类器行为的选项。
  • 显示名称语言区域:通过 TFLite 模型元数据指定的显示名称(如果有)的语言区域。
  • 结果数上限:要返回的评分最高的分类结果的数量上限。如果 <0,则返回所有可用的结果。
  • 分数阈值:低于此分数的结果将被拒绝。如果设置为 0,则返回所有可用的结果。
  • 类别许可名单:类别名称许可名单。如果为非空值,则类别不在此集合中的分类结果将被滤除。与拒绝名单相互排斥。
  • 类别拒绝名单:类别名称的拒绝名单。如果为非空值,则此集合中的类别将被滤除。与许可名单相互排斥。
    • 显示名称语言区域:any string
    • 结果数上限:any integer
    • 分数阈值:0.0-1.0
    • 类别许可名单:vector of strings
    • 类别拒绝名单:vector of strings
    • 显示名称语言区域:"en"
    • 结果数上限:-1
    • 分数阈值:0
    • 类别许可名单:空
    • 类别拒绝名单:空
    result_callback 设置结果监听器以接收分类结果 在手势识别器处于直播模式时异步执行。 仅在跑步模式设为“LIVE_STREAM”时才能使用 ResultListener 不适用 不适用

    准备数据

    将输入准备为图像文件或 Numpy 数组,然后将其转换为 mediapipe.Image 对象。如果您输入的是 网络摄像头,您可以使用外部库,如 OpenCV:以 Numpy 形式加载输入帧 数组。

    映像

    import mediapipe as mp
    
    # Load the input image from an image file.
    mp_image = mp.Image.create_from_file('/path/to/image')
    
    # Load the input image from a numpy array.
    mp_image = mp.Image(image_format=mp.ImageFormat.SRGB, data=numpy_image)
        

    视频

    import mediapipe as mp
    
    # Use OpenCV’s VideoCapture to load the input video.
    
    # Load the frame rate of the video using OpenCV’s CV_CAP_PROP_FPS
    # You’ll need it to calculate the timestamp for each frame.
    
    # Loop through each frame in the video using VideoCapture#read()
    
    # Convert the frame received from OpenCV to a MediaPipe’s Image object.
    mp_image = mp.Image(image_format=mp.ImageFormat.SRGB, data=numpy_frame_from_opencv)
        

    直播

    import mediapipe as mp
    
    # Use OpenCV’s VideoCapture to start capturing from the webcam.
    
    # Create a loop to read the latest frame from the camera using VideoCapture#read()
    
    # Convert the frame received from OpenCV to a MediaPipe’s Image object.
    mp_image = mp.Image(image_format=mp.ImageFormat.SRGB, data=numpy_frame_from_opencv)
        

    运行任务

    手势识别器使用 remember、recognize_for_video 和 recognize_async 函数来触发推理。对于手势识别,这涉及 预处理输入数据、检测图片中的手、检测手 以及从地标中识别手势。

    以下代码演示了如何使用任务模型执行处理。

    映像

    # Perform gesture recognition on the provided single image.
    # The gesture recognizer must be created with the image mode.
    gesture_recognition_result = recognizer.recognize(mp_image)
        

    视频

    # Perform gesture recognition on the provided single image.
    # The gesture recognizer must be created with the video mode.
    gesture_recognition_result = recognizer.recognize_for_video(mp_image, frame_timestamp_ms)
        

    直播

    # Send live image data to perform gesture recognition.
    # The results are accessible via the `result_callback` provided in
    # the `GestureRecognizerOptions` object.
    # The gesture recognizer must be created with the live stream mode.
    recognizer.recognize_async(mp_image, frame_timestamp_ms)
        

    请注意以下几点:

    • 在视频模式或直播模式下投放广告时,您还必须 为手势识别器任务提供输入帧的时间戳。
    • 在图片或视频模型中运行时,手势识别器任务将 阻塞当前线程,直到它处理完输入图像,或者 帧。
    • 在直播模式下运行时,手势识别程序任务不会阻止 当前线程,但会立即返回。它将调用其结果 监听器,并在每次完成处理时显示识别结果 输入帧。如果在手势识别程序检测到手势时调用了识别功能, 任务正忙于处理另一个帧,该任务将忽略新输入 帧。

    有关在图片上运行手势识别器的完整示例,请参阅代码 示例 了解详情。

    处理和显示结果

    手势识别程序会针对每个人 识别运行。结果对象包含图片坐标形式的手部特征点, 用世界坐标表示的手形地标、惯用手(左手/右手)和手用手势 所检测到的手的手势类别。

    以下示例展示了此任务的输出数据:

    生成的 GestureRecognizerResult 包含四个组成部分,每个组成部分都是一个数组,其中每个元素都包含所检测到的一只手的检测结果。

    • 惯用手

      惯用手表示检测到的手是左手还是右手。

    • 手势

      检测到的手的已识别手势类别。

    • 地标

      这里有 21 个手形标志,每个标志由 xyz 坐标组成。通过 xy 坐标按图片宽度和 高度。z 坐标表示地标深度, 手腕的深度就是起点。值越小, 最接近的是镜头。z的震级使用的刻度与 x

    • 世界地标

      21 个手形地标也以世界坐标表示。每个地标 由 xyz 组成,表示现实世界中的 3D 坐标 以指针的几何中心为起点

    GestureRecognizerResult:
      Handedness:
        Categories #0:
          index        : 0
          score        : 0.98396
          categoryName : Left
      Gestures:
        Categories #0:
          score        : 0.76893
          categoryName : Thumb_Up
      Landmarks:
        Landmark #0:
          x            : 0.638852
          y            : 0.671197
          z            : -3.41E-7
        Landmark #1:
          x            : 0.634599
          y            : 0.536441
          z            : -0.06984
        ... (21 landmarks for a hand)
      WorldLandmarks:
        Landmark #0:
          x            : 0.067485
          y            : 0.031084
          z            : 0.055223
        Landmark #1:
          x            : 0.063209
          y            : -0.00382
          z            : 0.020920
        ... (21 world landmarks for a hand)
    

    下图直观显示了任务输出:

    手势识别器示例代码演示了如何显示识别结果 结果,请参阅代码 示例 了解详情。