有什么汤菜谱大全| 包租婆是什么意思| 经常头晕是什么原因引起的| 留低是什么意思| 高铁上不能带什么东西| 早上口干舌燥是什么原因| 几朵花代表什么意思| 黄花鱼是什么鱼| 胃气上逆吃什么中成药| 儿童疝气挂什么科| 什么人不洗澡| 绿茶婊什么意思| 火加同念什么| o型血溶血是什么意思| 老来得子是什么意思| 身体抱恙是什么意思| 梅花什么颜色| 什么是三净肉| 肚脐左侧按压疼是什么原因| 淘宝什么时候成立的| 囊是什么意思| 什么是名媛| 羊肉不能和什么一起吃| 什么血型不招蚊子| 东南方向是什么位置| 胃寒可以吃什么水果| 胰岛素高是什么意思| 孕激素低吃什么补得快| 美洲大蠊主治什么病| 半夜十二点是什么时辰| 老出汗是什么原因| 梦见驴是什么意思| 为什么会经常流鼻血| 查幽门螺杆菌挂什么科| 骨折是什么意思| 胃强脾弱吃什么中成药| 囗腔溃疡吃什么维生素| 戾气什么意思| 西芹和芹菜有什么区别| 天蝎座的幸运色是什么| 什么原因导致打嗝| 大料是什么| 今天立冬吃什么| 低血压平时要注意什么| 亦女念什么| 乌龟下蛋预示着什么| 舍利子到底是什么| 什么人容易得心理疾病| aoerbo是什么牌子的手表| 梦见蜜蜂是什么预兆| 江诗丹顿属于什么档次| 子宫肌瘤挂什么科| 新生儿睡觉突然大哭是什么原因| 西兰花和什么菜搭配| 什么时候立夏| 尿培养能查出什么病| 溃疡用什么药| 日益是什么意思| 尿正常是什么颜色| 什么样的伤口需要打破伤风| 妊娠囊是什么| 人的肝脏在什么位置| 心肌缺血吃什么| 秋天什么时候| 2023年属什么生肖| 手脚心热是什么原因| 保险子是什么| 便秘吃什么中药| 肠痉挛有什么症状| 心脏积液吃什么药最好| 子宫增厚是什么原因| 扁平疣吃什么药| INS什么意思| 王维字什么| 大象是什么颜色| 天秤座是什么星座| 九寨沟在四川什么地方| 身份证后四位代表什么| 手腕发麻是什么原因| 吃什么可以补钾| 1月23日是什么星座| 麟字五行属什么| 臭鼬是什么动物| 什么是一体机| 尿路感染是什么原因造成的| 卵巢多囊症是什么原因造成| 什么的松脂| 憋是什么意思| 领结婚证需要带什么材料| 胡萝卜和什么榨汁好喝| 大作是什么意思| 部分导联t波改变是什么意思| 梦见老鼠是什么征兆| 勾践姓什么| 举不胜举的举是什么意思| 头疼发热是什么原因| 护理是做什么的| 凤雏是什么意思| 请辞是什么意思| 工字可以加什么偏旁| 梦见自己牙齿掉光了是什么征兆| 吃什么水果容易减肥| 男生为什么喜欢女生叫爸爸| 五十路是什么意思| 低血压适合吃什么食物| 一什么| 心口窝疼是什么原因| 功什么不什么| 小孩腰疼是什么原因引起的| 刘备的儿子叫什么| 跟腱炎挂什么科| 做生意的人最忌讳什么| 菠萝蜜什么季节最好吃| 如你所愿是什么意思| 出国要办什么证件| 冰糖和白糖有什么区别| ceq是什么意思| 什么是化疗| 柜姐是什么意思| 脑白质变性是什么意思| 解约是什么意思| 中央组织部部长什么级别| 脾大是怎么回事有什么危害| 汇报是什么意思| 林是什么生肖| 姨妈是什么意思| 凯旋归来是什么意思| 隐翅虫擦什么药膏| 镜子是什么生肖| 刺猬和豪猪有什么区别| 心心念念是什么意思| 自己是什么意思| 颈椎反曲是什么意思| 12月24是什么星座| 虎皮鹦鹉吃什么| 深褐色是什么颜色| 二月四号是什么星座| 蓝莓有什么好处| 胃出血什么症状| 蒲公英泡水喝有什么效果| 放屁很臭是什么原因| 空调水滴是什么模式| 古代上班叫什么| 复方阿胶浆适合什么样的人喝| 蝗虫用什么呼吸| 舌头发白有齿痕是什么原因| 精索静脉曲张什么症状| 付之一炬是什么意思| 东南角风水代表什么| 一个歹一个殇读什么| 婧五行属什么| 梦见怀孕是什么预兆| 湫是什么意思| 血脂和血糖有什么区别| 传教士是什么意思| 79年出生属什么生肖| 黑色上衣配什么颜色的裤子| 鲶鱼吃什么食物| 眼皮痒是什么原因| 茯苓什么人不能吃| 白内障是什么原因引起的| 流黄鼻涕吃什么药| 世界7大奇迹是什么| 嬴稷和嬴政什么关系| 平均红细胞体积偏低是什么原因| 一阴一阳是什么数字| 六味地黄丸什么牌子的好| 大便黄绿色是什么原因| 什么原因导致脑出血| 子宫肌瘤不能吃什么| 新疆是什么民族| 朝鲜为什么那么落后| 心脏肥大吃什么药好| 孕妇吃红枣对胎儿有什么好处| 郑板桥爱画什么| 痛风发作吃什么药| 1990年什么命| 脚趾脱皮是什么原因| 11月24日是什么星座| 长痔疮有什么症状| 什么体质容易长肿瘤| 开指是什么意思| 舌下腺囊肿挂什么科| abob是什么药| 王维是什么派诗人| 七五年属什么| 做完无痛人流需要注意什么| 生理盐水敷脸有什么作用| 卿卿是什么意思| 欧多桑是什么意思| 星座上升是什么意思| 力五行属什么| 计算机科学与技术是学什么的| 闲情雅致是什么意思| 死间计划到底是什么| 五花肉炖什么好吃| 西洋参吃了有什么好处| romantic是什么意思| 什么茶能去体内湿气| 什么是肺气肿| 超现实主义是什么意思| 孕妇吃香蕉对胎儿有什么好处| 心率变异性是什么意思| 手是什么生肖| 喝什么| 白带黄吃什么药| 感冒黄痰吃什么药| 了凡四训讲的是什么| 致字五行属什么| 眼睛老跳是什么原因| 肺在什么位置图片| 精神小伙什么意思| 众生是什么意思| 科学的尽头是什么| 自食恶果是什么意思| 醋酸纤维是什么面料| pvc是什么意思| 春梦了无痕是什么意思| 505是什么意思| 血热是什么原因| 山楂炖肉起什么作用| 肌无力是什么症状| 浇头是什么意思| 在家无聊可以干什么| 师弟是什么意思| 脸上长黑痣是什么原因| 气胸病是什么原因引起的| 小姑独处是什么意思| 重庆什么时候解放的| 舅父是什么意思| 做梦梦到蛆是什么意思| peni是什么意思| 1980年是什么年| 随诊复查是什么意思| 鹿查什么部首| 无花果什么品种最好吃| 贤惠是什么意思| 27岁属什么| 什么茶去火| 嗯嗯什么意思| 电气火灾用什么灭火| 粘米粉是什么粉| 橙字五行属什么| 肺部有问题一般会出现什么症状| 五月21号是什么星座| 肚子胀不消化吃什么药| 职业年金是什么| ua是什么牌子| 右肺纤维灶是什么意思| 焕字五行属什么| 什么是性骚扰| 翻身是什么意思| 榨菜是什么菜做的| 胆固醇偏高有什么危害| 生姜放肚脐眼有什么功效| 草是什么意思| 胎盘内血池是什么| 什么叫单亲家庭| 瑞五行属性是什么| 东莞有什么好玩的| 市监狱长是什么级别| 男人交公粮什么意思| 后脑勺出汗多是什么原因| 霉菌阳性是什么意思| 百度

# 小程序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 模型路径外,其他设置都不是必须的。

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

除了使用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 < modelChannel; ++c)
      {
        for (var h = 0; h < modelHeight; ++h)
        {
          const origH = Math.round(h * hRatio);

          const origHOffset = origH * origHStride;

          for (var w = 0; w < modelWidth; ++w)
          {
            const origW = Math.round(w * wRatio);

            const origIndex = origHOffset + origW * origWStride + c;

            const val = origData[origIndex] * (normalized_div[c]) - normalized_mean[c];

            dstInput[idx] = val;

            idx++;
          }
        }
      } 

      resolve();
    });
  }

# 2.3 模型推理

对摄像头采集到的数据进行简单前处理后,我们就可以用来设置 input,进行模型推理了。 我们用前处理得到的 dstInput 来构造一个 xInput,将这个 xInput 作为模型推理的输入,传递给 session.run 即可。

const xinput = {
    shape: [1, 3, 224, 224],  // 输入形状 NCHW 值
    data: dstInput.buffer,    // 为一个 ArrayBuffer
    type: 'float32',          // 输入数据类型
};

this.session.run({
    // 这里 "input" 必须与 ONNX 模型文件中的模型输入名保持严格一致
    "input": xinput,
})
.then((res) => {

    // 这里使用 res.outputname.data
    // 其中 outputname 需要严格与 ONNX 模型文件中的模型输出名保持一致
    let num = new Float32Array(res.output.data)

运行之后的结果我们通过 res.output 获取。 需要注意的是, 这里的 input/output 不是所有模型固定的,需要严格与具体 ONNX 文件中的输入,输出名字对应。 回到之前 Netron 看到的 mobilenet 模型描述信息:我们可以看到本模型有一个输入,名字叫做 “input”,有一个输出,名字就叫做 “output”。 因此我们设置输入时, session.run({"input": xinput}), "input" 即为 ONNX 模型中的 input name. 当有多个输入时,我们通过session.run({"input1": xxx, "input2": xxx}) 来分别对模型中名字为 “input1” 和 “input2” 的输入设置数据。 同样的,我们获取模型的输出时,res.output 指获取名字为 “output” 的输出。

不管是模型的输入还是输出 Tensor, 都是一个 Object,包含了 shape,type 和 data 三个属性。其中 data 是一块ArrayBuffer。

# 2.4 后处理

本示例对后处理过程比较简单,获取到模型输出后,我们通过一个 argMax 操作,计算出分数最高的分类 Index, 并将这个 Index 转换为所表示的类别即可。

let num = new Float32Array(res.output.data)

var maxVar = num[0];

var index = 0;

for (var i = 1; i < num.length; ++i)
{
if (maxVar < num[i])
{
    maxVar = num[i]   
    index = i     
}
}

this.getClass(index);

# 3 运行效果

扫描下方二维码,点击接口-通用AI推理能力-mobileNet, 可以查看运行效果。



运行 demo,可以看到摄像头在采集同时,将会实时地将分类结果写回到页面下方。



完整 demo 请参考官方github小程序示例

# 算子支持列表

详细算子支持情况请参考算子支持列表

眼眶疼是什么原因 女儿红属于什么酒 2013属什么生肖 1.4什么星座 行运是什么意思
什么是有机 菌群异常是什么意思 中旬是什么意思 脸上为什么会长斑 洋溢着什么样的笑容
黑镜讲的是什么 长期便秘吃什么药好 活塞是什么 12583是什么电话 黄瓜什么时候种植
望梅止渴的梅是什么梅 肛门指检是检查什么 屁股痛是什么原因 细菌性结膜炎用什么眼药水 去香港澳门旅游需要准备什么
大便不调是什么意思hcv9jop2ns9r.cn 起大运是什么意思hcv8jop9ns5r.cn 肚子疼吃什么食物好hcv9jop7ns5r.cn 儿童吃手指是什么原因hebeidezhi.com 失眠看什么科最好hcv7jop9ns4r.cn
二月二十二日是什么星座hcv7jop9ns9r.cn 做梦梦到鸡是什么意思beikeqingting.com bp什么意思hcv9jop7ns2r.cn 血压和血糖有什么关系hcv9jop1ns2r.cn 身上红痣多是什么原因bjhyzcsm.com
军分区司令是什么级别hcv9jop4ns1r.cn 甲状腺肿是什么意思aiwuzhiyu.com 女人梦见蛇预示着什么hcv9jop6ns9r.cn 猪和什么属相不合hcv7jop6ns6r.cn 纯天然无公害什么意思zhiyanzhang.com
女人大姨妈来了吃什么最好hcv8jop0ns6r.cn 1963属什么生肖hcv8jop7ns8r.cn 断崖式是什么意思hcv8jop7ns3r.cn 什么叫撤退性出血cj623037.com 角质是什么hcv7jop9ns1r.cn
百度