微信小程序扫描识别图片 --微信小程序 IOS下camera组件takePhoto时 有快门声音

时间:2024-03-04 07:51:26

需求:扫描识别实物,根据实物展示出对应的效果,实际就是一个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);
      }
    });

  },