借助 MediaPipe 手势识别器任务,你可以实时识别手势; 提供已识别的手势结果和 检测到手部设备。以下说明介绍了如何使用手势识别程序 支持 Android 应用这些说明中介绍的代码示例可供使用 (位于 GitHub 上)。
要了解此任务的实际运行情况,请查看 网络演示。 如需详细了解功能、模型和配置选项 部分,请参阅概览。
代码示例
MediaPipe Tasks 示例代码是手势识别器的简单实现 Android 版应用。该示例使用 Android 实体设备上的相机 持续检测手势,也可使用 设备图库来静态检测手势。
您可以用该应用作为基础来开发自己的 Android 应用,也可以指代该应用 对现有应用进行了修改。手势识别程序示例代码托管在 GitHub
下载代码
以下说明介绍了如何创建示例的本地副本 使用 git 命令行工具运行 git 代码库。
<ph type="x-smartling-placeholder">如需下载示例代码,请执行以下操作:
- 使用以下命令克隆 git 代码库:
git clone https://github.com/google-ai-edge/mediapipe-samples
- (可选)将您的 Git 实例配置为使用稀疏检出,
因此您只有手势识别器示例应用的文件:
cd mediapipe git sparse-checkout init --cone git sparse-checkout set examples/gesture_recognizer/android
创建示例代码的本地版本后,您可以导入项目 进入 Android Studio 并运行应用。有关说明,请参阅 Android 版设置指南。
关键组件
以下文件包含此手势的关键代码 识别示例应用:
- GestureRecognizerHelper.kt - 初始化手势识别器并处理模型和委托 选择。
- MainActivity.kt:
实现应用,包括调用
GestureRecognizerHelper
和GestureRecognizerResultsAdapter
。 - GestureRecognizerResultsAdapter.kt - 处理结果并设置其格式。
设置
本部分介绍了设置开发环境和 一些专门用于使用手势识别器的代码项目。有关 设置开发环境以使用 MediaPipe 任务,包括 平台版本要求,请参阅 Android 版设置指南。
<ph type="x-smartling-placeholder">依赖项
手势识别器任务使用 com.google.mediapipe:tasks-vision
库。将此依赖项添加到 Android 应用的 build.gradle
文件中:
dependencies {
implementation 'com.google.mediapipe:tasks-vision:latest.release'
}
型号
MediaPipe 手势识别器任务需要一个与 此任务。如需详细了解适用于手势识别程序且经过训练的模型, 请参阅任务概览的“模型”部分。
选择并下载模型,并将其存储在项目目录中:
<dev-project-root>/src/main/assets
在 ModelAssetPath
参数中指定模型的路径。在
示例代码,
该模型在 GestureRecognizerHelper.kt
中定义,
文件:
baseOptionBuilder.setModelAssetPath(MP_RECOGNIZER_TASK)
创建任务
MediaPipe 手势识别程序任务使用 createFromOptions()
函数来设置
任务。createFromOptions()
函数接受
配置选项如需详细了解配置选项
请参阅配置选项。
手势识别器支持 3 种输入数据类型:静态图片、视频文件和 实时视频流。您需要指定与 输入数据类型。选择与 输入数据类型,了解如何创建任务并运行推理。
映像
val baseOptionsBuilder = BaseOptions.builder().setModelAssetPath(MP_RECOGNIZER_TASK) val baseOptions = baseOptionBuilder.build() val optionsBuilder = GestureRecognizer.GestureRecognizerOptions.builder() .setBaseOptions(baseOptions) .setMinHandDetectionConfidence(minHandDetectionConfidence) .setMinTrackingConfidence(minHandTrackingConfidence) .setMinHandPresenceConfidence(minHandPresenceConfidence) .setRunningMode(RunningMode.IMAGE) val options = optionsBuilder.build() gestureRecognizer = GestureRecognizer.createFromOptions(context, options)
视频
val baseOptionsBuilder = BaseOptions.builder().setModelAssetPath(MP_RECOGNIZER_TASK) val baseOptions = baseOptionBuilder.build() val optionsBuilder = GestureRecognizer.GestureRecognizerOptions.builder() .setBaseOptions(baseOptions) .setMinHandDetectionConfidence(minHandDetectionConfidence) .setMinTrackingConfidence(minHandTrackingConfidence) .setMinHandPresenceConfidence(minHandPresenceConfidence) .setRunningMode(RunningMode.VIDEO) val options = optionsBuilder.build() gestureRecognizer = GestureRecognizer.createFromOptions(context, options)
直播
val baseOptionsBuilder = BaseOptions.builder().setModelAssetPath(MP_RECOGNIZER_TASK) val baseOptions = baseOptionBuilder.build() val optionsBuilder = GestureRecognizer.GestureRecognizerOptions.builder() .setBaseOptions(baseOptions) .setMinHandDetectionConfidence(minHandDetectionConfidence) .setMinTrackingConfidence(minHandTrackingConfidence) .setMinHandPresenceConfidence(minHandPresenceConfidence) .setResultListener(this::returnLivestreamResult) .setErrorListener(this::returnLivestreamError) .setRunningMode(RunningMode.LIVE_STREAM) val options = optionsBuilder.build() gestureRecognizer = GestureRecognizer.createFromOptions(context, options)
手势识别器示例代码实现允许用户在
处理模式这种方法使得任务创建代码更加复杂,
可能不适合您的用例。您可以在
setupGestureRecognizer()
函数,
GestureRecognizerHelper.kt
文件。
配置选项
此任务具有以下适用于 Android 应用的配置选项:
选项名称 | 说明 | 值范围 | 默认值 | |
---|---|---|---|---|
runningMode |
设置任务的运行模式。有三个
模式: IMAGE:单图输入的模式。 VIDEO:视频已解码帧的模式。 LIVE_STREAM:输入流媒体直播模式 例如来自相机的数据。在此模式下,resultListener 必须为 调用以设置监听器以接收结果 异步执行。 |
{IMAGE, VIDEO, LIVE_STREAM } |
IMAGE |
|
numHands |
最多能检测出手的数量
GestureRecognizer 。
|
Any integer > 0 |
1 |
|
minHandDetectionConfidence |
手部检测要计算的最低置信度分数 在手掌检测模型中被认为是成功的。 | 0.0 - 1.0 |
0.5 |
|
minHandPresenceConfidence |
手部存在分数的最低置信度分数 特征点检测模型。在手势识别程序的视频模式和直播模式下, 如果来自手部特征码模型的手部存在信心得分低于 达到此阈值后,就会触发手掌检测模型。否则, 轻量级的手部跟踪算法用于确定 进行后续地标检测。 | 0.0 - 1.0 |
0.5 |
|
minTrackingConfidence |
要考虑的手部跟踪的最低置信度分数 成功。这是两只手之间的边界框 IoU 阈值, 分别表示当前帧和最后一帧。处于视频模式和直播模式 手势识别程序,如果追踪失败,手势识别程序会触发手部 检测。否则,系统会跳过手部检测。 | 0.0 - 1.0 |
0.5 |
|
cannedGesturesClassifierOptions |
用于配置预设手势分类器行为的选项。预设的手势为 ["None", "Closed_Fist", "Open_Palm", "Pointing_Up", "Thumb_Down", "Thumb_Up", "Victory", "ILoveYou"] |
|
|
|
customGesturesClassifierOptions |
用于配置自定义手势分类器行为的选项。 |
|
|
|
resultListener |
设置结果监听器以接收分类结果
在手势识别器处于直播模式时异步执行。
仅在跑步模式设为“LIVE_STREAM ”时才能使用 |
ResultListener |
不适用 | 不适用 |
errorListener |
设置一个可选的错误监听器。 | ErrorListener |
不适用 | 不适用 |
准备数据
手势识别器支持图片、视频文件和直播视频。任务 处理数据输入预处理,包括调整大小、旋转和值 标准化。
以下代码演示了如何移交数据进行处理。这些 示例包括关于如何处理来自图片、视频文件和实时 视频流。
映像
import com.google.mediapipe.framework.image.BitmapImageBuilder import com.google.mediapipe.framework.image.MPImage // Convert the input Bitmap object to an MPImage object to run inference val mpImage = BitmapImageBuilder(image).build()
视频
import com.google.mediapipe.framework.image.BitmapImageBuilder import com.google.mediapipe.framework.image.MPImage val argb8888Frame = if (frame.config == Bitmap.Config.ARGB_8888) frame else frame.copy(Bitmap.Config.ARGB_8888, false) // Convert the input Bitmap object to an MPImage object to run inference val mpImage = BitmapImageBuilder(argb8888Frame).build()
直播
import com.google.mediapipe.framework.image.BitmapImageBuilder import com.google.mediapipe.framework.image.MPImage // Convert the input Bitmap object to an MPImage object to run inference val mpImage = BitmapImageBuilder(rotatedBitmap).build()
在
手势识别器示例代码,数据准备在
GestureRecognizerHelper.kt
文件。
运行任务
手势识别器使用 recognize
、recognizeForVideo
和 recognizeAsync
函数来触发推理。对于手势识别,这涉及
预处理输入数据、检测图片中的手、检测手部
以及从地标中识别手势。
以下代码演示了如何使用任务模型执行处理。 这些示例详细说明了如何处理来自图片、视频文件 和直播视频流
映像
val result = gestureRecognizer?.recognize(mpImage)
视频
val timestampMs = i * inferenceIntervalMs gestureRecognizer?.recognizeForVideo(mpImage, timestampMs) ?.let { recognizerResult -> resultList.add(recognizerResult) }
直播
val mpImage = BitmapImageBuilder(rotatedBitmap).build() val frameTime = SystemClock.uptimeMillis() gestureRecognizer?.recognizeAsync(mpImage, frameTime)
请注意以下几点:
- 在视频模式或直播模式下投放广告时,您还必须 向手势识别器任务提供输入帧的时间戳。
- 在图片模式或视频模式下运行时,手势识别程序任务将 阻塞当前线程,直到它处理完输入图像,或者 帧。为避免阻塞界面,请在 后台线程。
- 在直播模式下运行时,手势识别程序任务不会阻止 当前线程,但会立即返回。它将调用其结果 监听器,并在每次完成处理时显示识别结果 输入帧。如果在手势识别程序检测到手势时调用了识别功能, 任务正忙于处理另一个帧,则该任务将忽略新的输入帧。
在
手势识别器示例代码、recognize
、recognizeForVideo
和
recognizeAsync
函数在
GestureRecognizerHelper.kt
文件。
处理和显示结果
手势识别程序会针对每个人 识别运行。结果对象包含图片坐标形式的手部特征点, 用世界坐标表示的手形地标、惯用手(左手/右手)和手用手势 所检测到的手的手势类别。
以下示例展示了此任务的输出数据:
生成的 GestureRecognizerResult
包含四个组成部分,每个组成部分都是一个数组,其中每个元素都包含所检测到的一只手的检测结果。
惯用手
惯用手表示检测到的手是左手还是右手。
手势
检测到的手的已识别手势类别。
地标
这里有 21 个手形标志,每个标志由
x
、y
和z
坐标组成。通过x
和y
坐标按图片宽度和 高度。z
坐标表示地标深度, 手腕的深度就是起点。值越小, 最接近的是镜头。z
的震级使用的刻度与x
。世界地标
21 个手形地标也以世界坐标表示。每个地标 由
x
、y
和z
组成,表示现实世界中的 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)
下图直观显示了任务输出:
在
手势识别器示例代码,即以下部分中的 GestureRecognizerResultsAdapter
类:
GestureRecognizerResultsAdapter.kt
文件会处理这些结果。