小程序AI使用指南

您所在的位置:网站首页 推理Ai 小程序AI使用指南

小程序AI使用指南

2024-03-23 05:57| 来源: 网络整理| 查看: 265

# 小程序AI使用指南 # 开始

小程序AI通用接口是一套小程序官方提供的通用AI模型推理解决方案,内部使用充分优化的自研推理引擎,支持 CPU、GPU、NPU 推理。小程序开发者无需关注内部实现和模型转换,只需提供训练好的 ONNX 模型,小程序内部会将用户的 ONNX 模型自动转换为自研推理引擎可以识别的模型格式并完成推理。

本指南将展示如何从头开始使用小程序AI推理能力完成一个分类任务。我们将摄像头实时采集到的数据经过简单的前处理转换为AI推理的输入,完成推理后,再对模型运行输出进行简单的后处理,获取最终分类结果并展示在页面上。

示例使用 ONNX 官方 modelzoo 所提供的 mobileNetV2 模型。相关模型可以从官方github 获取;示例中使用的前后处理方式也与 ONNX 官方给出的imagenet_validation一致。

# 1 创建session

首先我们需要创建一个 session 用于推理。 这里我们使用从官方github下载的浮点模型,选择 precisionLevel 为0,这样 session 运行时,将会自动选择 fp16 存储中间 tensor 的结果,也会用 fp16 进行计算,并且会开启 fp16 计算的 Winograd,同时开启近似 math 计算。我们选择不使用量化推理,不使用 NPU。 创建 session 时除了必须提供参数 model 来指定 ONNX 模型路径外,其他设置都不是必须的。

一般来说,使用的 precesionLevel 等级越低,推理速度越快,但可能带来精度损失。因此推荐开发者在使用时,在效果满足需求时优先使用更低精度以提高推理速度,节约能耗。

除了使用wx.createInferenceSession()接口创建 session 外,此处我们还为 session 添加了2个事件,以监听 error 或者创建完成。onLoad()函数中我们通过设置一个 isReady 变量,记录 session 完成了初始化,可以用来进行推理。

// 这里 modelPath 为需要的 ONNX 模型,注意 model 目前只能识别后缀为.onnx 的文件作为参数。 const modelPath = `${wx.env.USER_DATA_PATH}/mobilenetv2-12.onnx`; this.session = wx.createInferenceSession({ model: modelPath, /* 0: 最低精度 使用 fp16 存储浮点,fp16 计算,Winograd 算法也采取 fp16 计算,开启近似 math 计算 1: 较低精度 使用 fp16 存储浮点,fp16 计算,禁用 Winograd 算法,开启近似 math 计算 2: 中等精度 使用 fp16 存储浮点,fp32 计算,开启 Winograd,开启近似 math 计算 3: 较高精度 使用 fp32 存储浮点,fp32 计算,开启 Winograd,开启近似 math 计算 4: 最高精度 使用 fp32 存储浮点,fp32 计算,开启 Winograd,关闭近似 math 计算 通常更高的精度需要更长的时间完成推理 */ precisionLevel : 0, allowNPU : false, // 是否使用 NPU 推理,仅针对 IOS 有效 allowQuantize: false, // 是否产生量化模型 }); // 监听error事件 session.onError((error) => { console.error(error); }); // 监听模型加载完成事件 session.onLoad(() => { console.log('session load') }); # 2 session推理 # 2.1 处理摄像头采集数据

首先我们创建一个 camera context, 并调用 onCameraFrame 采集帧。此处的 classifier 封装了推理 session 相关的调用,具体完整代码可以参考 demo 示例。onCameraFrame 会持续采集摄像头图像,如果我们的 session 初始化成功的并且完成了上一帧的推理任务,就会传递摄像头采集的数据,执行新一次的推理任务。

const context = wx.createCameraContext(this); const listener = context.onCameraFrame(frame => { const fps = this.fpsHelper.getAverageFps(); console.log(`fps=${fps}`); if (this.classifier && this.classifier.isReady() && !this.predicting) { this.executeClassify(frame); } }); # 2.2 对摄像头的采集数据进行前处理

OnCameraFrame 返回的 frame 包含属性 width、height 和 data,分别表示二维图像数据的宽度,高度,以及图像像素点数据。其中 data 为一个 ArrayBuffer,存储数据类型为 Uint8,存储的数据 format 为 rgba,即每连续的4个值表示一个像素点的 rgba。 详细关于 onCameraFrame 的内容可以参考CameraContext.onCameraFrame.

对于 frame 内容,我们首先进行前处理操作以转化为模型输入。

用 Netron 打开 ONNX 文件,我们可以看到 mobileNet 输入输出的描述信息。 可以看到,本模型的输入大小为[1, 3, 224, 224],数据类型为 float32。

为了将摄像头采集到的frame转换为模型需要的数据,我们需要丢弃 alpha 通道信息,将数据由 nhwc 变换成 nchw, 将 frame 的 width 和 height resize 成 224 x 224, 并且完成 normallize 操作。

以下代码通过 js 完成了所有前处理过程,将摄像头采集到 frame 转化为模型输入 dstInput。 其中 frame 为摄像头采集的数据, var dstInput = new Float32Array(3 * 224 * 224);

/* 原始输入为 rgba uint8 数据, 目标为 nchw float32 数据 将camera 采集数据缩放到模型的 input 大小, 将 uint8 数据转换成 float32, 并且从 NHWC 转换到 NCHW */ preProcess(frame, dstInput) { return new Promise((resolve, reject) => { const origData = new Uint8Array(frame.data); const hRatio = frame.height / modelHeight; const wRatio = frame.width / modelWidth; const origHStride = frame.width * 4; const origWStride = 4; const mean = [0.485, 0.456, 0.406] // Reverse of std = [0.229, 0.224, 0.225] const reverse_div = [4.367, 4.464, 4.444] const ratio = 1 / 255.0 const normalized_div = [ratio / reverse_div[0], ratio * reverse_div[1], ratio * reverse_div[2]]; const normalized_mean = [mean[0] * reverse_div[0], mean[1] * reverse_div[1], mean[2] * reverse_div[2]]; var idx = 0; for (var c = 0; c


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3