评论

小程序AR识别,三行代码实现Camera数据毫秒级转base64图片

小程序AR识别,三行代码实现Camera数据毫秒级转base64图片

关键词:小程序AR 图片 base64 相机 Camera onCameraFrame Canvas ArrayBuffer Uint8Array Uint8ClampedArray upng-js

核心步骤:

1 相机原始图像数据frame.data,即ArrayBuffer数组,转成Uint8Array数组

2 Uint8Array数组转成Uint8ClampedArray数组

3 wx.canvasPutImageData(Uint8ClampedArray)


详细流程如下:

最近因为项目需求,需要上传base64去做AR识别功能,和大家一起分享讨论下具体的实现方式。

首先说下实现原理,通过Camera的onCameraFrame获取实时帧数据,将实时帧数据添加到Canvas上,然后将Canvas保存为临时图片,再将临时图片转换为base64。

贴上核心实现代码:

wxml:

js:

var nCounter = 0;
openCamera: function (res) {
    var that = this
    var camera_ctx = wx.createCameraContext()
    listener = camera_ctx.onCameraFrame((frame) => {
      // nCounter等于30 是因为一开始相机会有一个对焦的过程,如果一开始获取数据,就是模糊的图片
      if (nCounter == 30) {
        console.log(frame.data instanceof ArrayBuffer, frame.width, frame.height)
        var data = new Uint8Array(frame.data);
        var clamped = new Uint8ClampedArray(data);
        // 实时帧数据添加到Canvas上
        wx.canvasPutImageData({
          canvasId: 'myCanvas',
          x: 0,
          y: 0,
          width: frame.width,
          height: frame.height,
          data: clamped,
          success(res) {
            // 转换临时文件
            wx.canvasToTempFilePath({
              x: 0,
              y: 0,
              width: frame.width,
              height: frame.height,
              canvasId: 'myCanvas',
              fileType: 'jpg',
              destWidth: frame.width,
              destHeight: frame.height,
              // 精度修改
              quality: 0.8,
              success(res) {
                // 临时文件转base64
                wx.getFileSystemManager().readFile({
                  filePath: res.tempFilePath, //选择图片返回的相对路径
                  encoding: 'base64', //编码格式
                  success: res => {
                    // 保存base64
                    that.data.mybase64 = res.data;               
                  }
                })
              },
              fail(res) {
                console.log(res);
              }
            }, that)
          }
        })
      }
      nCounter++
      // console.log(nCounter);
      if (nCounter >= 100) {
        nCounter = 0
      }
    })
    listener.start()
  }

目前网上有两种转换方式并对比下:

1:upng-js等第三方转码js库,将相机流转换成base64,一般需要1-2s左右

2.使用canvas将相机流转变base64,都是使用js或者小程序官方的api进行转换,一般转换时间在1秒以下:

重点说明下:

如何使用wx.canvasPutImageData()将相机流添加canvas,我们查看该官方api,添加的data类型为:Uint8ClampedArray

而我们通过onCameraFrame获取的data类型为:ArrayBuffer

所有两者类型不一致,就需要转换,将ArrayBuffer=>Uint8Array=>Uint8ClampedArray

var data = new Uint8Array(frame.data);
var clamped = new Uint8ClampedArray(data);

成功的把onCameraFrame获取实时帧数据转换并canvasPutImageData在canvas上,并通过canvasToTempFilePath获取临时文件,如何获取临时文件getFileSystemManager转换为base64,传入云端进行AR识别,就大功告成!

技术分享来自于:北京晞翼科技有限公司

技术作者:le3d618、xiaoz0816

微信商务联系:le3d618

最后一次编辑于  2020-04-30  
点赞 9
收藏
评论

6 个评论

  • 问路
    问路
    2020-05-27

    在测试机发现,这个方法,会造成越来越卡顿? 如何解决?

    2020-05-27
    赞同 2
    回复 8
    • wanderers
      wanderers
      2020-07-06
      有解决方法了吗
      2020-07-06
      回复
    • 王佩韦
      王佩韦
      2020-11-28回复wanderers
      2020-11-28
      2
      回复
    • 迪克
      迪克
      2021-01-28回复王佩韦
      您好  我再引用jpeg-js使用的时候  报Buffer is not defined ,这个问题您遇到过吗
      2021-01-28
      回复
    • ^_^
      ^_^
      2021-02-07回复王佩韦
      我也是
      2021-02-07
      回复
    • 一如往常
      一如往常
      2022-09-27
      同问
      2022-09-27
      回复
    查看更多(3)
  • VinPink
    VinPink
    2020-05-26

    还请大佬粘贴出源码啊

    2020-05-26
    赞同 1
    回复
  • lin
    lin
    2023-09-12

    errMsg: "canvasPutImageData:fail invalid data format"}

    2023-09-12
    赞同
    回复
  • ran
    ran
    2022-05-31

    请问 报错The provided value is not of type '(CSSImageValue or HTMLImageElement or SVGImageElement or HTMLVideoElement or HTMLCanvasElement or ImageBitmap or OffscreenCanvas)' 因为啥呀

    2022-05-31
    赞同
    回复
  • 常若水
    常若水
    2020-11-04

    官方的takePhoto也可以,将拍照的文件通过wx.getFileSystemManager转为base64上传

    2020-11-04
    赞同
    回复 3
    • 杨小北
      杨小北
      2020-12-07
      iOS拍照不会抖动吗?
      2020-12-07
      回复
    • luke
      luke
      2021-11-10
      拍照会存到相册里的。
      2021-11-10
      1
      回复
    • 棪燊
      棪燊
      03-06回复杨小北
      非常抖
      03-06
      回复
  • 梦!
    梦!
    2020-07-02

    upng在ios上有问题

    2020-07-02
    赞同
    回复
登录 后发表内容