![[canvas][camera][TensorFlow]项目采坑记录: 微信小程序逐帧上传 [canvas][camera][TensorFlow]项目采坑记录: 微信小程序逐帧上传](/img/no_img.png)
引入
项目需求:在前端使用camera组件持续扫描,将捕捉到的帧上传到后端进行算法识别判断,并返回判断结果。若结果为“成功”,则将捕捉到的正确帧显示在屏幕上。
尝试
wx.onCameraFrame(frame=>{
    //frame.width
    //frame.height
    //frame.data
}) 
wx.onCameraFrameAPI接受一个回调函数,返回frame的宽高和frame的图像编码(ArrayBuffer格式)
尝试(一)
经过查找,wx.arrayBufferToBase64API,可以实现arraybuffer到Base64的转换,但实际使用的过程中发现处理速度极其缓慢,并且对手机性能消耗太大,不满足实时性的需求
尝试(二)
后来发现了将arrayBuffer画到canvas上,再将canvas画布的图片导出为base64的方式,遂进行了尝试。
wx.canvasPutImageData 
wx.canvasToTempFilePath 
 wx.getFileSystemManager()  
采坑1
frame.data的格式为ArrayBuffer,不能直接上传,需要进行如下处理:
var data = new Uint8Array(frame.data);
var clamped = new Uint8ClampedArray(data);
 wx.canvasPutImageData({
          canvasId: 'getImg',
          x: 0,
          y: 0,
          width: frame.width,
          height: frame.height,
          data: clamped,
          success(res) { ... },
          fail(err) { ... }
} 
采坑2
fail canvas is empty
canvasPutImageData未绑定this 
解决方法:
在函数开头定义变量that指向this,并使用that绑定
//html
<canvas canvas-id="myCanvas"></canvas>
//js
onReady(){
    const that = this
    wx.canvasPutImageData({ 
        canvasId: 'myCanvas'
        ...
    },that)
}  
采坑3
wx.canvasToTempFilePath报错:"create bitmap failed"
在csdn中得到了解答:https://blog.csdn.net/txyzqc/...
用来存放图片的canvas不能设置
hidden="true",所以可以利用
position: absolute进行绝对定位,使得canvas脱离文档流,并通过设置top和left等位置,将canvas移出视口。 此时,"create bitmap failed"错误不再发生。  
渲染阻塞
问题:在实际使用中发现,由于在回调函数中频繁的进行setData操作,不断地触发了UI的渲染。导致画面非常不流畅。
解决方法:利用"加锁"的方式
data:{
    lock: true,
    queue:[]
}
...
const that = this
const listener = camera.onCameraFrame(frame=>{
    if(lock){
        queue.push(frame)
        that.setData({lock: false})
    }
})
...
listener.start({
    success(res){
        setInterval(()=>{
            let frame = queue[0]
            //处理frame
            queue.shift()
            lock = true
        },500)
    }
}) 
这样很好地限制了处理速度,保证setData尽量低频率调用,但实际体验中还是会有轻微卡顿(canvasToTempFilePath会阻塞渲染)。
图片上传
由于生成图片是个耗费性能的工作,所以理应使得传到后台的图片尽可能小,防止页面卡顿。但同时又需要将正确帧显示在页面上,这就造成了矛盾。
错误尝试:每次上传帧的同时进行拍照,若拍照返回的结果是正确的,则将拍照的本地图片进行展示。问题:1.拍照的声音在ios端无法关闭;2.拍照消耗性能;3. 由于返回正确结果需要时间(http请求),而在这段时间里camera组件展示的帧页面已经发生了改变,所以在做照片展示时会感受到突兀的回跳。 解决方式:在返回正确答案的瞬间进行拍照,这样性能的消耗较小,并且camera组件的帧画面是连续的。
最终解决方案:小程序部署TensorFlowJS
文档:https://github.com/GeekYmm/te...
最终效果:解决了卡顿问题,页面流畅体验良好。