需求:扫描识别实物,根据实物展示出对应的效果,实际就是一个camera然后弄了点动画伪装成扫描,然后截取图片,传给后端,后端进行识别。因为是快一年前的项目了 ,有些地方记不太清楚了。
开始是用camera组件takePhoto每500毫秒获取一次图片然后发送请求识别图片发现在 IOS下会有快门声音
this.cameraCtx.takePhoto({ quality: \'high\', success: (res) => { wx.uploadFile({ url: "https://****", method: "post", filePath: res.tempImagePath, name: \'file\', header: { "content-type": "multipart/form-data" }, success: (res) => { //..... } }); }, fail: () => { } });
快门声音是iOS系统的限制,除非用户静音,目前没办法关闭,于是又换成camera组件onCameraFrame(获取 Camera 实时帧数据)通过UPNG.js将实时帧数据转成base64,然后在
通过wx.getFileSystemManager().writeFile()将base64转成临时图片发送给后端进行图片识别。快门声是没有了,但是转出来的临时图片不够清晰,影响到识别的准确率,而且好像UPNG.js方法在真机上有些慢具体记不太清了。
import upng from \'../../utils/UPNG.js\'
this.cameraCtx.onCameraFrame((frame) => { this.transformArrayBufferToBase64(frame); });
//转化base64编码格式
transformArrayBufferToBase64: function (frame) {
let base64x = upng.encode([frame.data], frame.width, frame.height, 0)
let base64 = "data:image/png;base64," + wx.arrayBufferToBase64(base64x)
const fsm = wx.getFileSystemManager();
const FILE_BASE_NAME = \'tmp_base64src\';
const [, format, bodyData] = /data:image\/(\w+);base64,(.*)/.exec(base64) || [];
if (!format) {
console.log(\'format\')
console.log(base64)
return (new Error(\'ERROR_BASE64SRC_PARSE\'));
}
const filePath = `${wx.env.USER_DATA_PATH}/${FILE_BASE_NAME}.${format}`;
const buffer = base64x;
const _this = this
fsm.writeFile({
filePath,
data: buffer,
encoding: \'binary\',
success() {
wx.uploadFile({
url: "http://192.168.0.117:9000/searchVideo",
method: "post",
filePath: filePath,
name: \'file\',
header: {
"content-type": "multipart/form-data"
},
success: (res) => {
},
fail() {
}
});
},
fail() {
return (new Error(\'ERROR_BASE64SRC_WRITE\'));
}
})
},
因为图片不够清晰,于是又找到wx.canvasPutImageData画到canvas上然后用wx.canvasToTempFilePath返回个图片。(这么做好像是安卓手机上返回的图片大小有问题,影响到识别的准确率,具体记不太清楚了,反正是安卓有点问题)
<canvas id="tempCanvas" height="{{Height*2}}" width="{{Width*2}}" canvas-id="tempCanvas" style="width:{{Width}}px; height:{{Height}}px"></canvas>
this.cameraCtx.onCameraFrame((frame) => {
this.setData({
Height: frame.height,
Width: frame.width
})
var data = new Uint8Array(frame.data);
var clamped = new Uint8ClampedArray(data);
this.temframe = {};
this.temframe.width = frame.width;
this.temframe.height = frame.height;
this.temframe.data = clamped;
this.transformArrayBuffer();
});
transformArrayBuffer: function () {
var tf = this.temframe; var _this = this; console.log(tf) wx.canvasPutImageData({ canvasId: \'tempCanvas\', x: 0, y: 0, width: tf.width, height: tf.height, data: tf.data, success: function (res) { console.log(\'绘制成功\', res) _this.scaning = true; wx.canvasToTempFilePath({ x: 0, y: 0, width: tf.width, height: tf.height, canvasId: \'tempCanvas\', fileType: \'jpg\', destWidth: tf.width, destHeight: tf.height, // 精度修改 quality: 1, success(res) { console.log(res.tempFilePath) wx.uploadFile({url: "http://192.168.0.128:9000/searchVideo", method: "post", filePath: res.tempFilePath, name: \'file\', header: { "content-type": "multipart/form-data" }, success: (res) => { }, fail(res) { } }) }, fail(res) { console.log(\'console.log(res);\', res); setTimeout(() => { _this._takePhoto(); }, 500); } }); }, fail: function (e) { console.log(\'res\', e); setTimeout(() => { _this._takePhoto(); }, 500); } }); },
最后经过思考决定安卓手机用最开始的takePhoto获取图片,ios手机用wx.canvasPutImageData画到canvas的方法,这样图片清晰了,快门声音也没有了。
<canvas wx:if="{{system==\'ios\'}}" id="tempCanvas" height="{{Height*2}}" width="{{Width*2}}" canvas-id="tempCanvas" style="width:{{Width}}px; height:{{Height}}px"></canvas>
onLoad: function () { this.setData({ isShow: false }) this.temframe = {}; this.scanOk = false; this.scaning = false; this.cameraCtx = wx.createCameraContext();var _this = this wx.getSystemInfo({ success: function (res) { _this.setData({ pixelRatio: res.pixelRatio }) if (res.platform == "devtools") { _this.setData({ system: \'pc\' }) //PC } else if (res.platform == "ios") { _this.setData({ system: \'ios\' }) //IOS } else if (res.platform == "android") { _this.setData({ system: \'android\' }) } } }) setTimeout(this._takePhoto, 500); this.donghua() },
_takePhoto: function () {
if (this.scanOk || this.scaning) {
return false;
}
// ios和android区分获取图片方式
if (this.data.system == \'ios\') {
this.setData({
isReuqest: false
});
this.listener = this.cameraCtx.onCameraFrame((frame) => {
if (!this.data.isReuqest) {
this.setData({
Height: frame.height,
Width: frame.width
})
var data = new Uint8Array(frame.data);
var clamped = new Uint8ClampedArray(data);
console.log(frame.width, frame.height, clamped)
this.temframe = {};
this.temframe.width = frame.width;
this.temframe.height = frame.height;
this.temframe.data = clamped;
this.transformArrayBuffer();
}
});
this.listener.start()
} else {
const _this = this
this.cameraCtx.takePhoto({
quality: \'high\',
success: (res) => {
const context = wx.createCameraContext();
this.scaning = true;
wx.uploadFile({
url: "http://192.168.0.128:9000/searchVideo",
method: "post",
filePath: res.tempImagePath,
name: \'file\',
header: {
"content-type": "multipart/form-data"
},
success: (res) => {
this.scaning = false;
}
});
},
fail: () => {
setTimeout(() => {
this._takePhoto();
}, 500);
}
});
}
},
transformArrayBuffer: function () {
this.setData({
isReuqest: true
});
var tf = this.temframe;
var _this = this;
wx.canvasPutImageData({
canvasId: \'tempCanvas\',
x: 0,
y: 0,
width: tf.width,
height: tf.height,
data: tf.data,
success: function (res) {
console.log(\'绘制成功\', res)
_this.scaning = true;
wx.canvasToTempFilePath({
x: 0,
y: 0,
width: tf.width,
height: tf.height,
canvasId: \'tempCanvas\',
fileType: \'jpg\',
destWidth: tf.width,
destHeight: tf.height,
// 精度修改
quality: 1,
success(res) {
console.log(res.tempFilePath)
wx.uploadFile({
url: "http://192.168.0.128:9000/searchVideo",
method: "post",
filePath: res.tempFilePath,
name: \'file\',
header: {
"content-type": "multipart/form-data"
},
success: (res) => {
},
fail(res) {
console.log(\'fail识别失败\')
}
})
},
fail(res) {
setTimeout(() => {
_this._takePhoto();
}, 500);
}
});
},
fail: function (e) {
console.log(\'res\', e);
setTimeout(() => {
_this._takePhoto();
}, 500);
}
});
},