使用 MediaPipe 轻松实现设备端机器学习

MediaPipe介绍

MediaPipe是由Google开发的开源机器学习框架,旨在简化计算机视觉和媒体处理任务的开发。它提供了一种可扩展的方法来处理视觉数据,包括图像和视频,并可以在多种平台上运行,包括Android、iOS、Linux和Windows。以下是关于MediaPipe的详细介绍:

  1. 多用途的机器学习框架

    • MediaPipe设计用于执行各种计算机视觉和媒体处理任务,如姿势估计、手势识别、人脸检测、物体追踪、语义分割等。这使得它非常适合开发视觉应用程序,从AR体验到智能监视系统都可以使用。
  2. 跨平台支持

    • MediaPipe支持多个平台,包括移动设备(如Android和iOS)、桌面系统(如Linux和Windows)以及嵌入式系统。这使得开发者能够将其应用程序部署到各种设备上。
  3. 易于使用

    • MediaPipe提供了易于使用的API和工具,使开发者能够快速构建、训练和部署视觉模型。它还包括许多预构建的处理块,简化了通用任务的开发。
  4. 实时性能

    • MediaPipe旨在实现实时性能,可以处理高帧率的图像和视频流。这对于需要低延迟响应的应用程序(如AR和实时跟踪)非常重要。
  5. 开放源代码

    • MediaPipe是一个开放源代码项目,可以在GitHub上找到。这意味着开发者可以查看其源代码、提出问题、提交贡献,并自定义框架以满足其需求。
  6. 社区和生态系统

    • MediaPipe拥有活跃的社区支持,有许多示例代码和文档可供开发者使用。此外,它还与其他机器学习和计算机视觉库(如TensorFlow)集成,扩展了其功能和用途。

总之,MediaPipe是一个强大且多功能的机器学习框架,可用于构建各种视觉应用程序。无论您是专业的计算机视觉工程师还是初学者,都可以受益于其易用性和广泛的支持,用于实现各种机器学习任务。

  • MediaPipe:多平台设备上的ML解决方案
  • MediaPipe Studio:在设备上试用ML
  • MediaPipe Model Maker::使用数据集进行自定义

官网:https://developers.google.com/mediapipe

MediaPipe在Android端应用

MediaPipe主要用于视觉领域的应用,但它也可以在一定程度上用于文本和音频处理。以下是MediaPipe在这三个领域的应用以及在Android上的示例代码:

1. 视觉领域应用:

  • 姿势估计:识别人体的姿势,用于动作分析、体育训练等。
  • 人脸检测和分析:检测人脸、表情、年龄和性别。
  • 手势识别:检测手势,如拇指抬起、手掌手势等。
  • 物体追踪:追踪视频中的物体,可用于自动驾驶、监视等。

2. 文本领域应用:

  • 虽然MediaPipe不是主要用于文本处理的工具,但它可以与其他自然语言处理库结合使用,以处理文字数据。例如,您可以使用MediaPipe检测文本区域,然后使用文本识别库(如Tesseract)来提取文本。

3. 音频领域应用:

  • 同样,MediaPipe不是专门用于音频处理的工具,但它可以用于音频的特征提取和分析。例如,您可以使用它来检测声音中的关键事件,如声音强度或音调的变化。

对于Android上的示例代码,您可以查看MediaPipe的官方示例和文档,这些示例提供了详细的教程和示例代码,帮助您入门。以下是一些示例代码的链接:

这些示例包括许多视觉任务的示例,如姿势估计、人脸检测和手势识别。您可以通过查看这些示例代码来了解如何在Android应用程序中使用MediaPipe进行视觉任务的开发。请注意,文本和音频处理的示例可能需要与其他库结合使用,而不是MediaPipe自身完成。

视觉任务

对象检测器任务可让您检测多类对象的存在和位置。例如,物体检测器可以在图像中定位狗。这些说明向您展示如何在 Android 上使用对象检测器任务。

  • 依赖关系

对象检测器使用该com.google.mediapipe:tasks-vision库。将此依赖项添加到build.gradle您的 Android 应用程序开发项目的文件中。使用以下代码导入所需的依赖项:

dependencies {
    
    
    implementation 'com.google.mediapipe:tasks-vision:latest.release'
}
  • 模型

MediaPipe 对象检测器任务需要与此任务兼容的经过训练的模型。有关对象检测器的可用训练模型的更多信息,请参阅任务概述模型部分

选择并下载模型,然后将其存储在您的项目目录中:

<dev-project-root>/src/main/assets
  • 创建任务

您可以使用该createFromOptions函数来创建任务。该 createFromOptions函数接受配置选项,包括运行模式、显示名称区域设置、最大结果数、置信度阈值、类别允许列表和拒绝列表。如果未指定配置选项,则将使用默认值。有关配置选项的更多信息,请参阅配置概述。

对象检测器任务支持 3 种输入数据类型:静态图像、视频文件和实时视频流。创建任务时需要指定输入数据类型对应的运行模式。选择与您的输入数据类型相对应的选项卡,查看如何创建任务并运行推理。

ObjectDetectorOptions options =
  ObjectDetectorOptions.builder()
    .setBaseOptions(BaseOptions.builder().setModelAssetPath(‘model.tflite’).build())
    .setRunningMode(RunningMode.IMAGE)
    .setMaxResults(5)
    .build();
objectDetector = ObjectDetector.createFromOptions(context, options);

注意:如果您使用直播模式,请确保在创建任务时注册结果监听器。每当任务完成对视频帧的处理(以检测结果和输入图像作为参数)时,就会调用侦听器。
对象检测器示例代码实现允许用户在处理模式之间切换。该方法使任务创建代码更加复杂,并且可能不适合您的用例。ObjectDetectorHelper 您可以在类函数中看到这段代码 setupObjectDetector()。

  • 准备数据

您需要将输入图像或帧转换为 com.google.mediapipe.framework.image.MPImage对象,然后再将其传递到对象检测器。

以下示例解释并展示了如何为每种可用数据类型准备用于处理的数据:

import com.google.mediapipe.framework.image.BitmapImageBuilder;
import com.google.mediapipe.framework.image.MPImage;

// Load an image on the user’s device as a Bitmap object using BitmapFactory.

// Convert an Android’s Bitmap object to a MediaPipe’s Image object.
Image mpImage = new BitmapImageBuilder(bitmap).build();

在对象检测器示例代码中,数据准备是在 , ,函数ObjectDetectorHelper 中的类中处理的 。detectImage()detectVideoFile()detectLivestreamFrame()

  • 运行任务

根据您正在使用的数据类型,使用 ObjectDetector.detect…()特定于该数据类型的方法。用于 detect()单个图像、 detectForVideo()视频文件中的帧以及 detectAsync()视频流。当您对视频流执行检测时,请确保在单独的线程上运行检测,以避免阻塞用户界面线程。

以下代码示例显示了如何在这些不同的数据模式下运行对象检测器的简单示例:

ObjectDetectorResult detectionResult = objectDetector.detect(image);

对象检测器代码示例更详细地显示了每种模式的实现 detect()、 detectVideoFile()和detectAsync()。示例代码允许用户在处理模式之间切换,而您的用例可能不需要这些模式。

请注意以下事项:

1.在视频模式或直播流模式下运行时,您还必须向对象检测器任务提供输入帧的时间戳。
2.当在图像或视频模式下运行时,对象检测器任务将阻塞当前线程,直到完成对输入图像或帧的处理。为了避免阻塞当前线程,请在后台线程中执行处理。
3.在直播模式下运行时,对象检测器任务不会阻塞当前线程,而是立即返回。每次处理完输入帧时,它都会使用检测结果调用其结果侦听器。如果在对象检测器任务正忙于处理另一个帧时调用检测函数,则新的输入帧将被忽略。

  • 处理并显示结果

运行推理时,对象检测器任务返回一个 ObjectDetectorResult对象,该对象描述它在输入图像中找到的对象。

下面显示了此任务的输出数据的示例:

ObjectDetectorResult:
 Detection #0:
  Box: (x: 355, y: 133, w: 190, h: 206)
  Categories:
   index       : 17
   score       : 0.73828
   class name  : dog
 Detection #1:
  Box: (x: 103, y: 15, w: 138, h: 369)
  Categories:
   index       : 17
   score       : 0.73047
   class name  : dog

对象检测器示例代码演示了如何显示任务返回的检测结果。

文本任务

MediaPipe 文本分类器任务可让您将文本分类为一组定义的类别,例如正面或负面情绪。类别取决于您使用的模型以及该模型的训练方式。

  • 依赖关系

文本分类器使用这些com.google.mediapipe:tasks-text库。将此依赖项添加到build.gradle您的 Android 应用程序开发项目的文件中。您可以使用以下代码导入所需的依赖项:

dependencies {
    
    
    implementation 'com.google.mediapipe:tasks-text:latest.release'
}
  • 模型

MediaPipe 文本分类器任务需要与此任务兼容的经过训练的模型。有关文本分类器的可用训练模型的更多信息,请参阅任务概述模型部分

选择并下载模型,然后将其存储在您的项目assets 目录中:

<dev-project-root>/src/main/assets
  • 创建任务

使用文本分类器TextClassifier.createFrom…()函数之一准备运行推理的任务。您可以将该createFromFile() 函数与经过训练的模型文件的相对或绝对路径一起使用。下面的代码示例演示了该TextClassifier.createFromOptions() 函数的使用。有关可用配置选项的更多信息,请参阅 配置选项。

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

// no directory path required if model file is in src/main/assets:
String currentModel = "text_classifier_model.tflite";

fun initClassifier() {
    
    
    val baseOptionsBuilder = BaseOptions.builder()
        .setModelAssetPath(currentModel)
    try {
    
    
        val baseOptions = baseOptionsBuilder.build()
        val optionsBuilder = TextClassifier.TextClassifierOptions.builder()
            .setBaseOptions(baseOptions)
        val options = optionsBuilder.build()
        textClassifier = TextClassifier.createFromOptions(context, options)
    } catch (e: IllegalStateException) {
    
     // exception handling
    }
}

您可以在代码示例TextClassifierHelper 类函数中查看如何创建任务的示例 initClassifier()。

  • 准备数据

文本分类器适用于文本 ( String) 数据。该任务处理数据输入预处理,包括标记化和张量预处理。

所有预处理都在函数内处理classify()。无需事先对输入文本进行额外的预处理。

String inputText = "The input text to be classified.";
  • 运行任务

文本分类器使用该TextClassifier.classify()函数来运行推理。使用单独的执行线程来执行分类,以避免阻塞应用程序的 Android 用户界面线程。

以下代码演示了如何使用单独的执行线程来执行任务模型的处理。

    fun classify(text: String) {
    
    
        executor = ScheduledThreadPoolExecutor(1)

        executor.execute {
    
    
            val results = textClassifier.classify(text)
            listener.onResult(results)
        }
    }

您可以在代码示例TextClassifierHelper 类函数中查看如何运行任务的示例 classify()。

  • 处理并显示结果

文本分类器输出 a TextClassifierResult,其中包含输入文本的可能类别列表。类别由您使用的模型定义,因此如果您需要不同的类别,请选择不同的模型,或重新训练现有模型。

下面显示了此任务的输出数据的示例:

TextClassificationResult:
  Classification #0 (single classification head):
    ClassificationEntry #0:
      Category #0:
        category name: "positive"
        score: 0.8904
        index: 0
      Category #1:
        category name: "negative"
        score: 0.1096
        index: 1

这个结果是通过在输入文本上 运行BERT 分类器"an imperfect but overall entertaining mystery"获得的: 。

音频任务

MediaPipe 音频分类器任务允许您对音频数据执行分类。您可以使用此任务从一组经过训练的类别中识别声音事件。

  • 依赖

音频分类器使用该com.google.mediapipe:tasks-audio库。将此依赖项添加到build.gradle您的 Android 应用程序开发项目的文件中。使用以下代码导入所需的依赖项:

dependencies {
    
    
    implementation 'com.google.mediapipe:tasks-audio:latest.release'
}
  • 模型

MediaPipe 音频分类器任务需要与此任务兼容的经过训练的模型。有关音频分类器的可用训练模型的更多信息,请参阅任务概述模型部分。选择并下载模型,然后将其存储在您的项目目录中:

<dev-project-root>/src/main/assets
  • 创建任务

您可以使用该createFromOptions函数来创建任务。该 createFromOptions函数接受配置选项,包括运行模式、显示名称区域设置、最大结果数、置信度阈值以及类别允许列表或拒绝列表。有关配置选项的更多信息,请参阅配置概述。

音频分类器任务支持以下输入数据类型:音频剪辑和音频流。创建任务时需要指定输入数据类型对应的运行模式。选择与您的输入数据类型相对应的选项卡,查看如何创建任务并运行推理。

AudioClassifierOptions options =
    AudioClassifierOptions.builder()
        .setBaseOptions(
            BaseOptions.builder().setModelAssetPath("model.tflite").build())
        .setRunningMode(RunningMode.AUDIO_CLIPS)
        .setMaxResults(5)
        .build();
audioClassifier = AudioClassifier.createFromOptions(context, options);

音频分类器示例代码实现允许用户在处理模式之间切换。该方法使任务创建代码更加复杂,并且可能不适合您的用例。initClassifier()您可以在 的函数 中看到模式切换代码AudioClassifierHelper。

  • 准备数据

音频分类器适用于音频剪辑和音频流。该任务处理数据输入预处理,包括重采样、缓冲和成帧。但是,您必须先将输入音频数据转换为 com.google.mediapipe.tasks.components.containers.AudioData对象,然后再将其传递给音频分类器任务。

import com.google.mediapipe.tasks.components.containers.AudioData;

// Load an audio on the user’s device as a float array.

// Convert a float array to a MediaPipe’s AudioData object.
AudioData audioData =
    AudioData.create(
        AudioData.AudioDataFormat.builder()
            .setNumOfChannels(numOfChannels)
            .setSampleRate(sampleRate)
            .build(),
        floatData.length);
audioData.load(floatData);
  • 运行任务

您可以调用classify您的运行模式对应的函数来触发推理。音频分类器 API 返回输入音频数据中识别的音频事件的可能类别。

AudioClassifierResult classifierResult = audioClassifier.classify(audioData);

请注意以下事项:

在音频流模式下运行时,您还必须为音频分类器任务提供时间戳,以跟踪流中的哪些音频数据用于推理。
在音频剪辑模型中运行时,音频分类器任务会阻塞当前线程,直到完成对输入音频的处理。为了避免阻塞用户界面响应,请在后台线程中执行处理。
您可以查看使用音频剪辑运行音频分类器的示例,请参阅 代码示例AudioClassifierHelper中的类 。

  • 处理并显示结果

运行推理后,音频分类器任务返回输入音频中音频事件的可能类别列表。以下清单显示了此任务的输出数据的示例:

AudioClassifierResult:
  Timestamp in microseconds: 100
  ClassificationResult #0:
    Timestamp in microseconds: 100  
    Classifications #0 (single classification head):
      head index: 0
      category #0:
        category name: "Speech"
        score: 0.6
        index: 0
      category #1:
        category name: "Music"
        score: 0.2
        index: 1

在 Android 应用程序中,该任务返回一个ClassificationResult包含对象列表的AudioClassifierResult对象,表示音频事件的预测,包括类别标签和置信度得分。

// In the audio clips mode, the classification results are for the entire audio
// clip. The results are timestamped AudioClassifierResult objects, each
// classifying an interval of the entire audio clip that starts at
// ClassificationResult.timestampMs().get().

for (ClassificationResult result : audioClassifierResult.classificationResults()) {
    
    
  // Audio interval start timestamp:
  result.timestampMs().get();
  // Classification result of the audio interval.
  result.classifications();
}

猜你喜欢

转载自blog.csdn.net/weixin_44008788/article/details/132725184