WASMでOCR使ってみた
これは SMat Advent Calendar 2024 の12/17分の記事です。
弊社では「SmartMat Cloud」というIoT重量計 x SaaSでモノの流れを可視化するサービスを提供しております。最近お客様がスムーズにオンボーディングできるように、スマホのweb appのプロトタイプを作っております。当時のスプリントのゴールは商品の初回登録の時はスマートマットのシリアル番号や製品バーコードを読み取って検索するプロトタイプを狙いました。
バーコードリーダーはnpmのzxing-wasmがデファクトスタンダードでしたがスマートマットのシリアル番号はOptical Character Recognition(OCR)が必要でした。
OCR in the browser
OCRはtesseract.jsでしょう?と思いましたが、ocrsというプロジェクトが気になりました。
ocrsは、機械学習モデルを使用し、wasmにコンパイル可能であり、前処理ステップの代わりにより多くのML機能を使用することでtesseract.jsよりも速く動作するとされる。rustで書かれた新たなcli/ライブラリです。内部では、ocrsは異なるONNXモデルが必要な場合に使用できるように、ONNXモデルから変換されたrtenモデルを推論に使用しています。
Getting started: compile some wasm
https://github.com/robertknight/ocrs
を git clone
した後、以下のようなコマンドでwasmビルドを行うことができました:
cargo install wasm-bindgen-cli --version 0.2.89
rustup target add wasm32-unknown-unknown
sh ./ocrs/examples/download-models.sh
make wasm
ディレクトリは以下のようになりました:
.
├── index.js
├── package-lock.json
├── package.json
├── serialsample.jpg # テスト画像
├── text-detection.rten
└── text-recognition.rten
その後、サンプルのnodeアプリケーションが動作しました!
Integration: working with workers
パフォーマンスは重要であり、OCRロジックは可能な限りメインスレッドではないところで多くの作業を行うことになります。
これはワーカーを使用する絶好のケースです!このブログからワーカーを使ってパフォーマンスを向上させる方法について読んだ後、以下を実現できると確信しました:
- ワーカーとメインスレッド間のシグナルとして
SharedArrayBuffer
を使用する - 処理する画像を送信するために
postMessage
を使用する - メインスレッドから離れたワーカー内でWASMを使用する
- ワーカーの
postMessage
からキャンバスに結果を更新する
これは以下のようになります:
そして、個人のiPhone SES 3で約1秒の処理時間で動作しました。プロトタイプにとって十分に速く、改善の余地もあります。
まとめ
このスプリントはエンゲージングであり、WASMを使用してweb appが現在のパフォーマントに動作できるかを示すプロトタイプを作成する機会でした。
Discussion