如何利用Web Worker优化网页条码识别应用

现在主流的浏览器都支持WebRTC,通过getUserMedia可以在浏览器中轻松打开摄像头。Web开发者可以使用JavaScript开发网页版的条码扫描应用。通过Chrome和Safari的测试发现,当JS代码耗时多的时候,Chrome中的视频依然流畅,而Safari出现严重卡顿。推测Chrome的视频渲染和JavaScript不在一条线程中,不过如果要通过canvas来绘制UI依然会出现卡顿。要解决这个问题,可以把耗时多,计算量大的代码放到web worker中。

使用Web Worker加载执行JavaScript条形码识别库

条形码的检测接口可能会消耗几百毫秒的时间,所以把这部分放到web worker中。这里用到了Dynamsoft WebAssembly Barcode SDK.

创建worker.js并导入JavaScript条形码识别库:

function browserRedirect() {
    var deviceType;
    var sUserAgent = navigator.userAgent.toLowerCase();
    var bIsIpad = sUserAgent.match(/ipad/i) == "ipad";
    var bIsIphoneOs = sUserAgent.match(/iphone os/i) == "iphone os";
    var bIsMidp = sUserAgent.match(/midp/i) == "midp";
    var bIsUc7 = sUserAgent.match(/rv:1.2.3.4/i) == "rv:1.2.3.4";
    var bIsUc = sUserAgent.match(/ucweb/i) == "ucweb";
    var bIsAndroid = sUserAgent.match(/android/i) == "android";
    var bIsCE = sUserAgent.match(/windows ce/i) == "windows ce";
    var bIsWM = sUserAgent.match(/windows mobile/i) == "windows mobile";
    if (bIsIpad || bIsIphoneOs || bIsMidp || bIsUc7 || bIsUc || bIsAndroid || bIsCE || bIsWM) {
      deviceType = 'phone';
    } else {
      deviceType = 'pc';
    }
    return deviceType;
}

if (browserRedirect() === 'pc') {
    importScripts('https://demo.dynamsoft.com/dbr_wasm/js/dbr-6.3.0.1.min.js');
}
else {
    importScripts('https://demo.dynamsoft.com/dbr_wasm/js/dbr-6.3.0.1.mobile.min.js');
}

由于桌面和移动设备在性能上有差距,可以加载不同的版本。

初始化条码识别库:

var reader;
var dynamsoft = self.dynamsoft || {};
dynamsoft.dbrEnv = dynamsoft.dbrEnv || {};
dynamsoft.dbrEnv.resourcesPath = 'https://demo.dynamsoft.com/dbr_wasm/js/';

dynamsoft.dbrEnv.onAutoLoadWasmSuccess = function () {
    reader = new dynamsoft.BarcodeReader();
    postMessage({
        event: "onload",
        body: "Successfully loaded wasm."
    });
};
dynamsoft.dbrEnv.onAutoLoadWasmError = function (status) {
    postMessage({
        event: "onerror",
        body: "Failed to load wasm."
    });
};
//https://www.dynamsoft.com/CustomerPortal/Portal/TrialLicense.aspx
dynamsoft.dbrEnv.licenseKey = "t0068MgAAAD2IrA1WJjiVx78RfaZ46qMyCY8DaqpvAD57z5QWkwVQkVwZEf7lE+M2QYbnPx9Fu/aFvCL1mz0Kh2YK0milUng=";

识别解码JS主线程发送过来的视频图像:

onmessage = function (e) {
    e = e.data;
    switch (e.type) {
        case "decodeBuffer":
            {
                self.reader.decodeBuffer(e.body, e.width, e.height, e.width * 4, dynamsoft.BarcodeReader.EnumImagePixelFormat.IPF_ARGB_8888).then(results => {
                    postMessage({
                        event: 'onresult',
                        body: results
                    });
                }).catch(ex => {
                    postMessage({
                        event: 'onresult',
                        body: 'No barcode detected'
                    });
                });
                break;
            }
        default:
            break;
    }
};

在主线程中获取发送视频帧:

function scanBarcode() {

  let context = ctx,
    width = videoWidth,
    height = videoHeight;

  context.drawImage(videoElement, 0, 0, width, height);
  var barcodeCanvas = document.createElement("canvas");
  barcodeCanvas.width = width;
  barcodeCanvas.height = height;
  var barcodeContext = barcodeCanvas.getContext('2d');
  barcodeContext.drawImage(videoElement, 0, 0, width, height);
  // read barcode
  if (myWorker) {
    myWorker.postMessage({
      type: 'decodeBuffer',
      body: barcodeContext.getImageData(0, 0, width, height).data,
      width: width,
      height: height
    });
  }
}

最后把结果画出来:

function drawResult(context, localization, text) {
  context.beginPath();
  context.moveTo(localization.X1, localization.Y1);
  context.lineTo(localization.X2, localization.Y2);
  context.lineTo(localization.X3, localization.Y3);
  context.lineTo(localization.X4, localization.Y4);
  context.lineTo(localization.X1, localization.Y1);
  context.stroke();

  context.font = "18px Verdana";
  context.fillStyle = '#ff0000';
  let x = [localization.X1, localization.X2, localization.X3, localization.X4];
  let y = [localization.Y1, localization.Y2, localization.Y3, localization.Y4];
  x.sort(function (a, b) {
    return a - b
  });
  y.sort(function (a, b) {
    return b - a
  });
  let left = x[0];
  let top = y[0];

  context.fillText(text, left, top + 50);
}

在浏览器中的运行效果:

浏览器条形码识别

Source Code

https://github.com/dynamsoft-dbr/javascript-barcode/tree/master/examples/webworker

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值