2020年5月8日金曜日

スマホで使えるスキャナー Photo Scanner を作った

なんとなく欲しくなったので、スマホで使えるスキャナー Photo Scanner を作りました。 巷のハードウェアのスキャナーには以下のような不満があったので解決しました。
  1. スキャンに時間が掛かる → カメラ撮影で即スキャン
  2. 持ち運びが面倒 → スマホだけでOK

Photo Scanner



特に1についてですが、ハードウェアのスキャナーは、紙の設置に 5-10 秒、スキャンと転送に 5秒、排他制御や wake-up に 5-30秒、だいたいの感覚として 1枚あたり 15-45秒も時間が掛かってしまいます。 ちょっとスキャンの量が増えると、気付いたら1時間経ってることがしばしば。 Photo Scanner ではスマホでパシャパシャと写真を撮ればいいので、スペックが十分なら非常に短時間で全行程が完了します。

実行時間や持ち運びの問題があるため、もともとスマホのカメラをスキャナー替わりにしている人もいるかも知れません。 ただその場合、画像が歪んだり、照明の影響を受けてしまいます。 再利用しやすいデータにするのは大変、という欠点があります。 Photo Scanner ではスマホで適当にパシャパシャと写真を撮るだけで、スキャナーのように綺麗な整形データを出力します。 実現するために以下をやってます。
  1. 自動切り抜き+角度補正
  2. 自動ノイズ除去

1. 自動切り抜き+角度補正

自動切り抜き+角度補正は、深く考えずに構築した Deep Learning モデル だと、良い精度が出ませんでした。 何となくは動くんだけど、実用上はそれだと困る。 頭で考えると簡単に思える処理だけど、何も考えず単純な EfficientNet などで解こうとすると相性悪いと思う。知見。 今回は OpenCV.js で対処しました。以下のようなルールで処理しています。
  • 物体全体を画像内に収めてもらい最大面積を被写体とする
  • 被写体が四角形なら切り抜き、ついでに色々補正 (オプションで設定可)
様々な形の切り抜きも対応できたかも知れないけど、被写体が四角形かどうかで全然精度が違うので、割り切って文書専用にしました。 Semantic Segmentation も考えはしたけど、正確な 4 点切り抜きでも難しかったことから、戦う気は起きなかった。 OpenCV.js でも机の上で写真を撮ればエラーが出ることはほぼないので、ひとまず良しとしました。 カラフルや輪郭が不明確なものは、下に白い枠紙を置くなどすれば判定できる。 考え始めるとキリがないので、教科書やプリント類ならだいたい動くくらいの精度を目指しました。

このような補正アプリは類似製品がいくつかあるのですが、手動補正に重きを置くか、速度と快適さに重きを置くかで方針が分かれているように見えます。 このアプリは後者に重きを置いており、私はプリント類を高速処理したり、データセット作るのに活用している。

2. 自動ノイズ除去

ノイズ除去は、OpenCV.js でも書類なら問題なく使えますが、まさに AutoEncoder の出番なので、両方作ってみました。 OpenCV.js は影の濃淡を消しつつ強力にノイズを除去します。 AutoEncoder のノイズ除去はほんのりと自然に除去するようなモデルです。 両方作ってみると、まだまだ OpenCV.js のほうが使いやすそうな感じはしてます。 ひとまずわかりやすいデータを学習しただけなので、改善はしていきたい。


処理のポイントは以上です。 静的サービスにしたかったので、OpenCV.js をカスタム化して 2MB で実行できるようにしました。 Tensorflow.js + 量子化モデルも 1.3MB しかないので、Web アプリでも全然いけますね。 良い時代になったものです。

あとは実物を触ってみてください。 念のため書いておくと、スマホや getUserMedia がほぼ前提になるので、IE はサポート対象外です。 オフラインでも動くように PWA で作ってはいますが、iOS だと getUserMedia が動かないので、ファイルのアップロードからカメラを動かします。 このへんの仕組み、環境依存過ぎて困る。

0 件のコメント: