wasmでマルチバーコードスキャナを高速化した


この記事はこちらでも紹介しています。
https://cloud.flect.co.jp/entry/2020/05/01/131657

こんにちは。この前の投稿では、TeamsやZoomで自分をアニメ絵にする方法をご紹介しました。

FLECT: https://cloud.flect.co.jp/entry/2020/04/02/114756
Qiita: https://qiita.com/wok/items/eb4946f3a94453e4f2ba
Medium: https://medium.com/analytics-vidhya/how-to-edit-the-image-stream-for-video-chat-teams-zoom-part-3-convert-to-anime-84a6788819d2

キャッチーな内容なのでそこそこ反応があって嬉しかったです。

今回は、だいぶ毛色の違いますが、バーコードスキャナとwasmの話をします。

昨今、スマホが普及して誰でも簡単にITに接することが出来る時代になり、ユーザ体験の向上が大変重要になっています。
ユーザ体験の向上の観点で一つ重要な考え方として、いかに「特別なソフトウェアをインストールせずに利用できるサービスを提供する」ががあると思います。
わけのわからない(失礼)ソフトウェアを闇雲にスマホに入れたくないですよね。
そこで、このインストールを避けるために、スマートフォンのブラウザ上で動くソフトウェアを開発し、提供する場合があります。

一方で、一般的に、ブラウザ上で動くソフトウェアはネイティブアプリと比較すると応答性能が劣化する、という問題があります。
応答性能の劣化は直接ユーザ体験にも影響しますので、場合によってはブラウザ上で動かすことによるメリットよりデメリットが勝ってしまうことも考えられます。
このような問題を回避する手段として、ブラウザ上で動くソフトウェアを高速化するWebAssembly(wasm)という技術1を使うことがあります。
今回は、スマートフォンのブラウザ上で動くマルチバーコードスキャナをwasmを用いて高速化した話をご紹介します。

結果、こんな感じで結構高速で動くようになりました。

マルチバーコードスキャナとWebAssembly

今回言及しているマルチバーコードスキャナとは、スマートフォンのカメラで写した複数のバーコードを同時に読み取る技術です。
マルチバーコードスキャナとしては、スイスを拠点とするスタートアップのScanditが提供するMatrixScanが有名です。
リンク先の動画を見ていただければ一瞬で理解していただけると思いますが、とにかく応答性能が早い。そして精度も高い。
マルチバーコードスキャナの開発にとりかかろうとしたときに、この応答性能と精度を見せつけられ心が折れかけたのを鮮明に覚えています。自分で独自に開発する意味があるのか?と。
ただ、このMatixScanはネイティブアプリのみサポートとなっており(2020/4/30 時点)ブラウザではサポートされていません。
また、有料ですので、サービスやプロダクトにインテグレートするためにはライセンス料を支払う必要がある、というのも気になります。

といったように自分が考える要件に微妙に合致しないことから、独自にインテグレート可能なソフトウェアコンポーネントとして、スマートフォンのブラウザ上で動く高速高性能なマルチバーコードスキャナを開発することとなりました。

独自のマルチバーコードスキャナを開発するといっても、
世の中にはJavascriptで提供されているバーコードスキャナは複数あるので一から作るのではなく、OSSを活用することになります。
ただネイティブアプリより遅い。どうやって高速化するかと悩んでいるときに、ebayがバーコードスキャナにwasmを使って高速化した話を公開しているのを見つけました。

これを参考に、我々もwasmを用いて高速化を試みました。
以下、OSSのバーコードスキャナライブラリをwasm化したときの流れと、応答性能の評価をご紹介します。

バーコードスキャナのwasm化

今回wasm化するOSSのバーコードスキャナはzxingです。

このライブラリを選んだ理由は、次の2つです。

  • もともと開発していたマルチバーコードスキャナでJavascript版のものを利用していたから。
  • 既にwasm化するリポジトリが公開されており、導入のハードルが低いそうだから。

では、早速wasm化を進めていきます。
基本的には上記リポジトリのreadmeに記載されている内容を実施すれば良いですが、少し古い情報となっているので、一部修正が必要となります。

まずはwasmを作成するための環境設定を行いましょう。すでに環境をお持ちの方はスキップしてください。

作業内容はリポジトリからクローンしてbuildすることになりますが、ほぼ自動化されているので迷うことはないかと思います。
詳細は公式のページを参照ください。
https://emscripten.org/docs/getting_started/downloads.html

$ git clone https://github.com/emscripten-core/emsdk.git
$ cd emsdk
$ ./emsdk install latest
$ ./emsdk activate latest
$ source ./emsdk_env.sh

次に、zxingのwasm化のリポジトリからクローンを作成してください。

公式の方法だとWindows版の方法が記載されているため、ここでは敢えてLinuxでのコマンドを記載しておきます。
また、公式の方法だとコマンドが古くて動きませんので、置き換えが必要です。

$ git clone https://github.com/yushulx/zxing-cpp-emscripten
$ cd zxing-cpp-emscripten/build-wasm
$ sed -i.old s/emconfigure/emcmake/ configure.sh # このコマンド入れ替えが必要。(2020/4/30現在)
$ ./build.sh

さて、これで下記のとおり、2つのファイルが作成されたと思います。

下記のものがwasm化されたzxingのファイルとなります。

$ ls zxing.*
zxing.js  zxing.wasm

とても簡単ですね。

wasm化されたバーコードスキャナの性能

これを使ってどれくらい高速化されるのかを確認してみましょう。
実はこの性能比較は上記のリポジトリでも公開されているのですが測定環境が不明だったので、
今回は次のgoogleのPixel3とPixel4の2つのスマホで測定してみたいと思います。

また、zxingは、スキャンして読み取れなかった場合何度かリトライするという挙動をとるので、
読み取りやすいバーコードと、読み取りづらいバーコードで応答性能が変わってきます。さらに、画像のサイズによっても応答性能が変わってくると思います。
そこで、今回は、次の2つのバーコードを使って処理速度を評価しました。

  • 1つ目(下図Barcode01)は、適当な環境で撮影したバーコード。(381px x 155px)
  • 2つ目(下図Barcode02)は、OSSでジェネレートしたきれいなバーコード。(433px x 221px)

1000回スキャンした場合の処理時間の結果は次のようになりました。

Barcode01については、Pixel3,4共に、ざっくりJSだと17〜18秒程度のものがwasmだと4〜6秒になっています。

Barcode02については、Pixel3,4共に、ざっくりJSだと11秒程度のものがwasmだと3〜4秒になっています。

この結果から、wasm化により大体3〜4倍の高速化ができたと言えそうです。

ライブラリを置き換えるだけで、これだけの高速化が実現できるというのはかなり魅力的ですね。wasmが注目されるのもうなずける結果です。

なお、この評価を行ったプログラムは次のURLにアップしてあるので興味のある方は追試してみてください。(実験用なので、作りは乱暴です。)

最後に

今回はマルチバーコードスキャナで使用しているバーコードスキャンライブラリをwasm化しました。
実際のバーコードをスキャンさせて処理速度を評価した結果、wasm化により大体3〜4倍の高速化が期待できることがわかりました。
同じ機能のライブラリをwasm化したものに置き換えるだけでこれだけの性能向上が期待できるのであれば、
性能問題の対策としてまずはwasm化を検討、ということが増えてくるかもしれません。

ユーザ体験の向上にwasm化はとても重要な技術だと思いますので、引き続き注視していきたいと思います。

以下、この技術を組み込んだスマートフォンのブラウザ上で動くマルチバーコードスキャナのデモです。
興味を持たれた方は、是非ご連絡をいただければと思います。

設定次第でこんな感じに向きが違っていても一気にスキャンできます。(Pixel4で撮影)


  1. 仕様と言われたり、言語と言われたりもします。ここが詳しい