MediaPipe-UnityPlugin的基本使用

MediaPipe介绍

我们直接引用前人的智慧:MediaPipe介绍

而 MediaPipeUnityPlugin,则帮我们把MediaPipe(C++)移植到了C#,使其能被Unity调用


MediaPipeUnityPlugin

使用这个插件,你可以:
– 用 C# 编写 MediaPipe 代码
– 在Unity上运行 MediaPipe 的官方解决方案
– 在Unity上运行您的自定义 Calculator 和 CalculatorGraph
(根据输入/输出的类型,您可能需要编写 C++ 代码)

1. 安装

github地址:https://github.com/homuler/MediaPipeUnityPlugin

下载地址:https://github.com/homuler/MediaPipeUnityPlugin/releases
本文使用的版本:MediaPipeUnity.0.11.0

建议Unity版本:2021.3以上


2. 运行一个官方解决方案

当然,该插件已经提供了案例,此处目的是了解它的运作方式,以便你想要按自己的需求搭一个环境

GraphRunner

Graph运行基类,封装了config的加载及初始化配置、MediaPipe数据流的输入输出,相当于MVC中的M

  • 应用层 xxxGraph : GraphRunner
    声明具体的输出流并配置
    定义输入流的输入接口
    定义获取同步输出的接口
    定义异步输出监听的接口
    加载需要的数据文件

Solution

操作基类,负责图像处理程序的生命周期,管理并获取图像源,相当于MVC中的C

  • 派生类 ImageSourceSolution<T> : Solution
    -T : GraphRunner
    -管理GraphRunner实例及一些组件
    -实现具体的每帧更新逻辑
    抽象接口
    – OnStartRun() 初始化
    – AddTextureFrameToInputStream(TextureFrame textureFrame) 将图像传给输入流
    – WaitForNextValue() 获取同步输出

  • 应用层 xxxSolution : ImageSourceSolution<xxxGraph>
    -声明回调,在 OnStartRun() 中绑定Graph的异步监听接口,获取异步输出,并处理
    -在 AddTextureFrameToInputStream() 中将得到的图像传给自己的Graph实例
    -在 WaitForNextValue() 中获取Graph的同步输出,并处理

    扫描二维码关注公众号,回复: 16066252 查看本文章

Bootstrap

引导程序,选择图像输入源、资源加载方式、CPU或GPU计算,由Solution在Start()中调用

  • 图像源:WebCamera、Image、Video
    根据选择的图像源,需要挂上相应的组件
    WebCamSource
    StaticImageSource
    VideoSource
  • 资源加载:StreamingAssets、AssetBundle、Local

TextureFramePool

TextureFrame 的对象池,ImageSourceSolution 会用到

Screen

将图像源输出到一个 RawImage,由 ImageSourceSolution 管理


3. 原始流程

插件文档:https://github.com/homuler/MediaPipeUnityPlugin/wiki/Getting-Started

1)CalculatorGraph

MediaPipe的核心计算器

  • 每个 CalculatorGraph 都有自己的配置(CalculatorGraphConfig),在初始化时进行配置:
    (这部分由GraphRunner帮我们完成)

方式一:声明时直接传入文本

new CalculatorGraph("Config文本");

方式二:构建一个CalculatorGraphConfig然后传入

var graph = new CalculatorGraph();
var config = CalculatorGraphConfig.Parser.ParseFromTextFormat("Config文本");
graph.Initialize(config);

如下为一个简单的config:

var configText = @"
input_stream: ""in""
output_stream: ""out""
node {
  calculator: ""PassThroughCalculator""
  input_stream: ""in""
  output_stream: ""out1""
}
node {
  calculator: ""PassThroughCalculator""
  input_stream: ""out1""
  output_stream: ""out""
}
";

var graph = new CalculatorGraph(configText);

插件中已预设多个config可以直接使用

  • 完事后调用 StartRun() 启动
    (这一步需要我们在xxxGraph中调用)
graph.StartRun().AssertOk();

StartRun会返回一个 Status 表示结果
调用 Status.AssertOk() 检查结果,如果不正常则抛出异常
插件中大部分方法都会返回一个Status

如果我们的config中配置了副产物 SidePacket,则启动时还需要传一个进去

graph.StartRun(sidePacket).AssertOk();

2)Packet

在 MediaPipe 中,输入输出是数据包Packet的形式进行传输
Packet需要具体的派生,并指定数据的类型

  • 要将一个输入Packet传递给CalculatorGraph,我们使用 CalculatorGraph.AddPacketToInputStream()
var input = new StringPacket("Hello World!"); // 这是一个字符串Packet
graph.AddPacketToInputStream("输入流的名称", input).AssertOk();

(这部分也由GraphRunner帮我们完成,但需要xxxGraph提供一个外部输入接口)

其中 “输入流的名称” 在config中定义,即 “input_stream”,同理下面的 “输出流的名称” 为config中的 “output_stream”

  • 要从CalculatorGraph中获取一个输出Packet,我们先要添加一个输出流
var poller = graph.AddOutputStreamPoller<string>("输出流的名称").Value();

实际使用时建议先检查一下status

var statusOfPoller = graph.AddOutputStreamPoller<string>("输出流的名称");
if (statusOfPoller.Ok())
{
    
    
    var poller = statusOfPoller.Value();
}  

然后可以获取输出

var output = new StringPacket();
poller.Next(output); // 输出到这个Packet
Debug.Log(output.Get()); // 获取Packet里的数据

(这部分封装了一个OutputStream类帮我们完成)

3)传输图像

  1. ImageSourceSolution 从 WebCamera 或其他图像源中得到画面Texture
  2. Texture 经过 Solution 处理成为 TextureFrame,传递给Graph
  3. GraphRunner 将 TextureFrame 处理成为 ImageFrame,然后打包成 ImageFramePacket 输入到 CalculatorGraph

使用案例:基于MediaPipeUnityPlugin的三维手势追踪

猜你喜欢

转载自blog.csdn.net/EdmundRF/article/details/130312601