フレクトのクラウドblog re:newal

http://blog.flect.co.jp/cloud/からさらに引っ越しています

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

こんにちは。研究開発室の岡田です。(所属変わりました。)

前回は、TeamsやZoomで自分をアニメ絵にする方法をご紹介しました。

cloud.flect.co.jp

業務から少し離れていましたがキャッチーな内容なので結構評判が良かったみたいです。 今回は、FLECTの業務に関連する内容をご紹介したいと思います。

FLECTは、ユーザ体験の向上を重視したサービス、プロダクトの提案をさせていただいています。 その中で重要な考え方の一つとして、「特別なソフトウェアをインストールせずに利用できるサービスを提供する」があります。 具体的にはスマートフォンのブラウザ上で動くソフトウェアを開発し、提供することになります。

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

今回は、FLECTが開発しているスマートフォンのブラウザ上で動くマルチバーコードスキャナをwasmを用いて高速化した話をご紹介します。

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

f:id:Wok:20200501062054g:plain

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

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

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

FLECT独自のマルチバーコードスキャナを開発するといっても、 世の中には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)

f:id:Wok:20200501055102p:plain

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

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

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

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

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

f:id:Wok:20200501055257p:plain

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

barcode-wasm-test.herokuapp.com

最後に

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

今後もFLECTはユーザ体験の向上の為、様々な技術開発を進めていきます。wasm化は重要な技術として注視していきたいと思います。

最後に宣伝ですが、FLECTでは、この技術を組み込んだスマートフォンのブラウザ上で動くマルチバーコードスキャナの開発をしています。 興味を持たれた方は、是非ご連絡をいただければと思います。

FLECTのマルチバーコードリーダは、設定次第でこんな感じに向きが違っていても一気にスキャンできます。(Pixel4で撮影) f:id:Wok:20200501064539g:plain

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