Dynamsoft vs Scandit: 基於WebAssembly的JavaScript Barcode SDK深度評測

如果你想開發基於瀏覽器的HTML5條形碼掃描應用,你可以在Google首頁中找到最好的JavaScript Barcode SDK.

在這裏插入圖片描述

Dynamsoft和Scandit這兩家公司都開發了基於WebAssembly的條形碼SDK,可以讓Web應用的掃碼性能接近原生應用。我們可以從hello world入手,來深度體驗下這兩個SDK之間的差異。

Hello World快速入門

Dynamsoft

網址:https://www.npmjs.com/package/dynamsoft-javascript-barcode

  • 提供完整的示例代碼
  • 在沒有license的情況下,依然可以識別,只是結果無法完整顯示

在這裏插入圖片描述

  • 所有攝像頭使用默認邏輯。物體水平移動方向和筆記本內置攝像頭畫面方向相反
  • 分辨率可選
  • 默認支持所有主流類型的1D/2D條形碼
  • 默認識別多個條形碼

Scandit

網址:https://www.npmjs.com/package/scandit-sdk

  • 沒有提供完整代碼。用戶需要逐段拷貝到HTML頁面裏
  • 強制使用license。在沒有license的情況下無任何反應和提示
  • 對攝像頭進行了判斷。筆記本的內置攝像頭做了鏡像,物體運動方向和畫面方向保持一致
  • 沒有可選分辨率
  • 無默認條形碼類型,不設置就無法使用
  • 默認最多識別1個條形碼

入門對比

Hello World Sample Dynamsoft Scandit
是否提供完整代碼
無License可否運行
是否可以切換攝像頭
是否可以選擇分辨率
是否支持各種碼型
是否支持多碼識別

靜態圖片條形碼識別

Dynamsoft

支持多種輸入類型,接口非常豐富。

  • decode(source: Blob | Buffer | ArrayBuffer | Uint8Array | Uint8ClampedArray | HTMLImageElement | HTMLCanvasElement | HTMLVideoElement | string): Promise<TextResult[]>
  • decodeBase64String(base64: string): Promise<TextResult[]>
  • decodeBuffer(buffer: Uint8Array | Uint8ClampedArray | ArrayBuffer | Blob | Buffer, width: number, height: number, stride: number, format: EnumImagePixelFormat, config?: any): Promise<any>
  • decodeUrl(url: string): Promise<TextResult[]>

參考文檔:https://www.dynamsoft.com/help/Barcode-Reader-wasm/classes/barcodereader.html#decodebuffer

Scandit

只支持Uint8Array。必須先把數據通過HTML5的canvas解碼之後才能調用接口識別,非常不方便。

  • processImage(imageData: Uint8Array | HTMLImageElement, highQualitySingleFrameMode?: boolean): Promise<ScanResult>

參考文檔:https://docs.scandit.com/stable/web/classes/scanner.html

性能對比

爲了統一測試條件,傳入數據使用Uint8Array:

<input type="file" id="barcode-file" onchange="loadfile()" accept=".jpg,.jpeg,.png,.bmp" />

function loadfile() {
            let name = document.getElementById('barcode-file');
            var img = document.getElementById('image');

            var reader = new FileReader();
            reader.onload = function (evt) {
                img.onload = function () {
                    var canvas = document.createElement('canvas');
                    canvas.width = img.width;
                    canvas.height = img.height;
                    var context = canvas.getContext('2d');
                    context.drawImage(img, 0, 0);
                    var buffer = context.getImageData(0, 0, canvas.width, canvas.height).data;
                    // TODO: call barcode decoding API
                };
                img.src = evt.target.result;
            };
            reader.readAsDataURL(name.files[0]);
        };

解碼耗時的一個重要因素是傳入圖像的尺寸。傳入圖像大,耗時多,傳入圖像小,耗時少。

Dynamsoft提供的接口是對原圖解碼,而Scandit的接口內部會對圖像進行壓縮,因此如果傳入圖片尺寸很大,Dynamsoft接口就會比較耗時。但是通過canvas壓縮圖像之後,會發現Dynamsoft的接口耗時大幅下降。在處理複雜條形碼或者多條形碼的圖片時,Dynamsoft的性能優勢對比Scandit非常大。

以下代碼用於縮小圖片:

var ratio = 0.6;
var canvas = document.createElement('canvas');
var tmpWidth = img.width, tmpHeight = img.height;

while (tmpWidth > 1000 || tmpHeight > 1000) {
    tmpWidth *= ratio;
    tmpHeight *= ratio; 
}
canvas.width = tmpWidth;
canvas.height = tmpHeight;
                    
var context = canvas.getContext('2d');
context.drawImage(img, 0, 0, img.width, img.height, 0, 0, canvas.width, canvas.height);

在參數設置的時候,儘可能保持一致。靜態圖片中可能包含很多條形碼,比如文檔。所以最大條形碼數量都設置成了20。

Dynamsoft參數設置:

(async () => {
            barcodereader = await Dynamsoft.BarcodeReader.createInstance();
            await barcodereader.updateRuntimeSettings('balance');
            let settings = await barcodereader.getRuntimeSettings();
            settings.expectedBarcodesCount = 20;
            barcodereader.updateRuntimeSettings(settings);
        })();

Scandit參數設置:

scanditScanner = new ScanditSDK.Scanner({ imageSettings: {}, scanSettings: new ScanditSDK.ScanSettings({gpuAcceleration: true, enabledSymbologies: ["ean8", "ean13", "upca", "upce", "qr", "code93", "codabar", "code128", "aztec", "data-matrix", "maxicode", "pdf417"], maxNumberOfCodesPerFrame: 20 }) });

測試圖片

在這裏插入圖片描述

圖像壓縮前的解碼時間:

在這裏插入圖片描述

在這裏插入圖片描述

圖像壓縮後的解碼時間:

在這裏插入圖片描述

在這裏插入圖片描述

從數據看出,圖片縮放前後,Scandit的性能跨度不是很大。而Dynamsoft的性能提升非常明顯,受圖片尺寸的影響比較大。

再來看下多碼場景測試。 在這裏插入圖片描述 在設置了最大條碼數量20之後,Dynamsoft可以解出20個條形碼:

在這裏插入圖片描述

而Scandit的算法可能主要專注在移動使用場景(條形碼比較少),所以碰到多碼的圖,表現不理想:

在這裏插入圖片描述

從MP4視頻文件中識別條形碼

視頻文件可以當作模擬攝像頭,用於測試連續幀下,不同SDK之間的性能。 視頻文件必須和HTML文件放在同一個目錄才能正常加載。代碼如下:

function loadvideo() {
            let name = document.getElementById('videofile');
            performanceReport.innerHTML = "";

            videoContainer = document.getElementById('videoContainer');
            videoContainer.src = name.files.item(0).name;
            videoContainer.addEventListener("loadedmetadata", function (e) {
                var width = this.videoWidth,
                    height = this.videoHeight;
                console.log(width, height);
            }, false);

            videoContainer.addEventListener("playing", function () {
                decoding_start = 0;
                isPlaying = true;
                decodeVideo(this.videoWidth, this.videoHeight);
            });

            videoContainer.addEventListener("pause", function () {
                isPlaying = false;
            });
        };

通過loadedmetadata事件可以獲得視頻幀的寬高。

視頻幀可以通過context.drawImage(videoContainer, 0, 0, width, height, 0, 0, canvas.width, canvas.height);繪製到canvas上。讀取方法和靜態圖片一樣。

在我的視頻測試中,Scandit的平均耗時相對少點。對比靜態圖片,參數做了修改。最大條形碼數量都設成了1,支持的碼型都改成了3個。

Dynamsoft開啓了速度模式:

(async () => {
            barcodereader = await Dynamsoft.BarcodeReader.createInstance();
            await barcodereader.updateRuntimeSettings('speed');
            let settings = await barcodereader.getRuntimeSettings();
            settings.expectedBarcodesCount = 1
            settings.barcodeFormatIds = Dynamsoft.EnumBarcodeFormat.BF_CODE_128 | Dynamsoft.EnumBarcodeFormat.BF_UPC_A | Dynamsoft.EnumBarcodeFormat.BF_QR_CODE;
            barcodereader.updateRuntimeSettings(settings);
        })();

Scandit關閉了高質量檢測模式,減少耗時:

scanditScanner = new ScanditSDK.Scanner({ imageSettings: {}, scanSettings: new ScanditSDK.ScanSettings({ gpuAcceleration: true, enabledSymbologies: ["code128", "qr", "upca"], maxNumberOfCodesPerFrame: 1 }) });

scanditScanner.processImage(buffer)

運行結果:

在這裏插入圖片描述

在這裏插入圖片描述

攝像頭掃碼

在商用場景中,攝像頭實時掃碼的需求比較多。用HTML5開發掃碼app的成本也會比原生應用低不少。

攝像頭列表

Dynamsoft提供了一個接口來獲取攝像頭列表:

cameras = await scanner.getAllCameras();

Scandit沒有提供攝像頭列表接口,默認只支持前後攝像頭,完全是針對手機的設計。那麼要獲取攝像頭列表並顯示在下拉菜單中,只能自己寫代碼實現:

navigator.mediaDevices.enumerateDevices().then(gotDevices);
        var index = 0;
        function gotDevices(cameras) {
            for (var i = 0; i < cameras.length; i++) {
                
            }
        }

攝像頭切換

Dynamsoft提供了攝像頭切換接口:

await scanner.setCurrentCamera()

Scandit也提供了切換接口:

scanditScanner.setActiveCamera()

但是通過編程發現,Scandit的接口在PC上無法正常工作。要正常切換,只能通過銷燬來重新創建:

scanditScanner.destroy(true);
createScanditScanner()

性能對比

640x480的分辨率下,Dynamsoft因爲用了多幀處理算法,解碼速度比Scandit更快。不過在使用更高分辨率的時候,Dynamsoft因爲是對全圖解碼的,性能會比Scandit差。所以在使用Dynamsoft接口的時候,可以通過設置scanner._canvasMaxWH = 640,把任意大的圖像壓縮到640x480來提速。

在這裏插入圖片描述

在這裏插入圖片描述

Scandit的畫面相比Dynamsoft略顯模糊,因爲Scandit通過CSS做了全屏顯示。但實際獲取的視頻尺寸和Dynamsoft是完全一樣的,也是640x480。

關於硬件優化

Dynamsoft提供了SIMD CPU指令優化。

Scandit提供了基於WebGL的GPU加速。

文檔頁面

Dynamsoft https://www.dynamsoft.com/help/Barcode-Reader-wasm/

Scandit https://docs.scandit.com/stable/web/index.html

源碼

https://github.com/yushulx/dynamsoft-scandit-javascript-barcode

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章