项目需求:在前端使用camera
组件持续扫描,将捕捉到的帧上传到后端进行算法识别判断,并返回判断结果。若结果为“成功”,则将捕捉到的正确帧显示在屏幕上。
wx.onCameraFrame(frame=>{ //frame.width //frame.height //frame.data })
wx.onCameraFrame
API接受一个回调函数,返回frame的宽高和frame的图像编码(ArrayBuffer格式)
经过查找,wx.arrayBufferToBase64
API,可以实现arraybuffer到Base64的转换,但实际使用的过程中发现处理速度极其缓慢,并且对手机性能消耗太大,不满足实时性的需求
后来发现了将arrayBuffer画到canvas上,再将canvas画布的图片导出为base64的方式,遂进行了尝试。
wx.canvasPutImageData
wx.canvasToTempFilePath
wx.getFileSystemManager()
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) { ... } }
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) }
wx.canvasToTempFilePath
报错:"create bitmap failed"
在csdn中得到了解答:https://blog.csdn.net/txyzqc/...
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会阻塞渲染)。
由于生成图片是个耗费性能的工作,所以理应使得传到后台的图片尽可能小,防止页面卡顿。但同时又需要将正确帧显示在页面上,这就造成了矛盾。
文档:https://github.com/GeekYmm/te...
最终效果:解决了卡顿问题,页面流畅体验良好。