【ML Kitで】来場者が身に着けたQRコードを自動取得するAI Marker(α版)の話【Androidアプリ開発】

はじめに

こんにちは、R&Dチームの加藤です。Raspberry Pi4を買った*1ので、まずは3Dプリンタでケースを作ります。今日はそんなRaspberry Piの話・・・ではなく、AI Markerについて技術寄りに説明したいと思います。

AI Markerとはなんぞや

お時間のある方はこちらのリンクを見ていただくと理解がスムーズです。

とにかく本題に急ぎたい方向けにざっくり紹介するとスマートフォンのカメラを使って二次元バーコードを認識、管理するための製品です。
セールスポイントは以下の通りです。

  • スマートフォンと二次元バーコードがあればすぐに開始可能で、運用コストが最小限
  • OPTiM AI Cameraなどの自社製品との連携が可能
  • 導線分析、顔に依らない個人識別、荷物管理などのシーンで活躍

OPTiM INNOVATION 2019でAI Markerお披露目

2019/10/24-25にOPTiMは初のプラベートショー「OPTiM INNOVATION 2019」を目黒雅叙園にて開催しましたが、AI Markerはこれが初お披露目&初本番投入でした。

会場の様子がこちらになります。赤枠を付けたのがAI Markerの端末です。α版のため今後にご期待ください。

f:id:optim-tech:20191217182502j:plain

このように、当日はAI Marker検出中の表記がしてありました。

f:id:optim-tech:20191224184017j:plain

本記事ではこのAI Markerの舞台裏を出血大サービスで紹介します。

必要なスペック

AI Markerに求められるスペックは以下の通りです。

  • 必達目標
    • カメラはブース上部から取り付ける
    • ブースから1メートル程度離れたところにいる人のQRコード*2を読み取りたい
    • 約40か所のブースに設置したい(Android端末が運用コスト的に理想)
  • 努力目標
    • 運用コスト削減のために来場者の参加申込に記載されているQRコードを流用したい
    • クラウドでデータを可視化したい
    • 来場者にリアルタイムで通知したい(来場ありがとうございますなど)

今回はとにかく時間がない*3かつ本番一発勝負なので、無理せず努力目標は割り切りました。 来場者の参加申込書に記載のQRコードは情報量が多いため、受付で簡易なQRコードを配布することにしました。 それでも、約40か所のブースで来場者が身に着けた小さなQRコードを正確に認識するのは個人的にもかなり挑戦的でした。

技術選定

AI Markerを実現するにあたって、先ほど示したスペックを達成できる技術の選定が必要です。ソフト、ハード両面で課題を解決していきます。

QRコードのライブラリ選定

やはり一番の肝はQRコードの認識精度ですね。今回はいくつかのQRコードのライブラリを候補としてピックアップしました。

精度としては、ML Kit>zxing≧pyzbar>OpenCVでした。検出精度が優秀かつAndroidアプリのサンプルコードがあるML Kitを採用しました。
ちなみに、OpenCVのQRコード検出のみ現状でマルチ検出に対応していません。しかし、マルチ検出のプルリクエストが出ているので、気長に待ちましょう*4

ML Kitは便利

ML Kitを使うことで誰でも簡単にDeep Learningによる物体検出や文字認識が可能になります。
今回は、GitHubにあるquickstart-androidのmlkitを参考にコードをAI Markerを作成しています。

quickstart-android/mlkit紹介

quickstart-androidは非常に多機能ですが、簡単に使用できます。 手元にandroid端末がある方は是非試してみましょう。
インストールは簡単です。

  1. Android端末は事前に開発者モードにしておく
  2. quickstart-androidをgit cloneしてくる
  3. firebaseの設定をして、google-services.jsonをapp直下に配置
  4. Android Studioでquickstart-android下のmlkitを選択して「OK」
  5. Android端末をPCに接続し、「run'app'」を実行

Android端末にインストールすると言語選択画面が出てきます*5。 流行りはKotlinですが、ここは歴史と実績のあるJavaを選択してみます。

f:id:optim-tech:20191213172438p:plain:w360

次に画像の取得方法を聞いてくるので、Liveモードにしてみましょう。 カメラが起動します*6

f:id:optim-tech:20191213172444p:plain:w360

ここまでくると、好きな検出器を使用できます。 左下の文字をタップすると、色々選べることがわかります。

f:id:optim-tech:20191213172449p:plain:w360

  1. Face Contour
  2. Face Detection
  3. AutoML Vision Edge
  4. Object Detection
  5. Text Detection
  6. Barcode Detection
  7. Label Detection
  8. Classification (quantized)
  9. Classification (float)

今回は太字の項目を紹介していきます。
まずは顔検出(Face Contour/Face Detector)
happinessが0.92と高得点ですね(Face Detectorの仕様の詳細はこちら)。

f:id:optim-tech:20191213172458p:plain:w360 f:id:optim-tech:20191213172509p:plain:w360

次に物体検出(Object Detection)*7。Foodと正しく認識していますね。

f:id:optim-tech:20191213172517p:plain:w360

次に文字検出(Text Detection)*8
個人的にはこの文字検出が一番感動しました。カロリーメイトの「C」が検出できているし、小さい文字も画質が悪くてもそこそこ正確です。

f:id:optim-tech:20191213172526p:plain:w360 f:id:optim-tech:20191213172535p:plain:w360

最後に紹介するのはバーコード検出(Barcode Detection)。これです。これが今回使いたい検出器ですね。
OPTiM INNOVATION 2019のAI Markerデモでは、このML Kitのバーコード検出をカスタマイズして使用しています*9

f:id:optim-tech:20191213172542p:plain:w360

(おまけ)QRコードの精度向上について

他にも色々試して精度向上を達成していますが、お手軽に精度を向上させる方法を二つ記載しておきます。
一つ目はカメラキャプチャの解像度の変更です。修正箇所は以下の通りです。

--- a/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/common/CameraSource.java
+++ b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/common/CameraSource.java
@@ -54,8 +54,8 @@ public class CameraSource {
   public static final int IMAGE_FORMAT = ImageFormat.NV21;
-  public static final int DEFAULT_REQUESTED_CAMERA_PREVIEW_WIDTH = 480;
-  public static final int DEFAULT_REQUESTED_CAMERA_PREVIEW_HEIGHT = 360;
+  public static final int DEFAULT_REQUESTED_CAMERA_PREVIEW_WIDTH = 1920;
+  public static final int DEFAULT_REQUESTED_CAMERA_PREVIEW_HEIGHT = 1440;

二つ目は、バーコード検出をQRコードのみに設定しておきます。

--- a/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/java/barcodescanning/BarcodeScanningProcessor.java
+++ b/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/java/barcodescanning/BarcodeScanningProcessor.java
@@ -22,6 +22,7 @@ import com.google.android.gms.tasks.Task;
 import com.google.firebase.ml.vision.barcode.FirebaseVisionBarcodeDetector;
+import com.google.firebase.ml.vision.barcode.FirebaseVisionBarcodeDetectorOptions;
 import com.google.firebase.ml.vision.common.FirebaseVisionImage;
@@ -46,7 +47,11 @@ public class BarcodeScanningProcessor extends VisionProcessorBase<List<FirebaseV
         // new FirebaseVisionBarcodeDetectorOptions.Builder()
         //     .setBarcodeFormats(FirebaseVisionBarcode.FORMAT_QR_CODE)
         //     .build();
-        detector = FirebaseVision.getInstance().getVisionBarcodeDetector();
+        detector = FirebaseVision.getInstance().getVisionBarcodeDetector(
+                new FirebaseVisionBarcodeDetectorOptions.Builder()
+                        .setBarcodeFormats(FirebaseVisionBarcode.FORMAT_QR_CODE)
+                        .build());
+
     }

これだけでQRコードの認識精度がある程度向上するので、ぜひ試してみてください。

(番外編)ARマーカーじゃダメなの?

当然ながらQRコードに縛られる必要はありません。ARマーカーのライブラリは現状以下の通りです。

精度としては、ML Kitに並ぶ精度を達成してくれたのですが以下の二つの欠点があり、採用を見送っています。

  • Javaで使える商用利用可能な無料のライブラリがない(ライセンス問題)
  • 格納できるデータ数が少ない(12bit程度なので、複数のARマーカーを組み合わせたりする必要)

どちらも自作で解決しますが、今回は開発期間の関係で見送りました。

取得したQRコードの管理

当然ながら、QRコードを使って来場者の行動分析が目的なのでQRコードキャプチャを作っただけではダメです。QRコード管理の全体の流れを以下の図に示します。

  1. QRコードをキャプチャ
  2. 一定時間ログを確保
  3. ログを定期書き込み

f:id:optim-tech:20191217145729p:plain

ここからは私がつまずいたポイントについて、ソースコードを交えつつ紹介します*10

時刻の取得

SimpleDateFormatを使用して時刻を取得しました。"yyMMdd-HH:mm:ss"は2019年12月23日の12時34分56秒を例にすると、"191223-12:34:56"となります。

public String getTime(){
        Calendar c = Calendar.getInstance();
        SimpleDateFormat sdf = new SimpleDateFormat("yyMMdd-HH:mm:ss", Locale.JAPAN);
        return sdf.format(c.getTime());
}

ファイル名の決定

約40台の端末のログを解析する必要があるので、Android IDを利用してそれぞれ固有のファイル名を設定するようにしました。
今回の端末はAndroid Oで40台同じ機種となるので、別々のIDが払い出されることを確認して採用しました。

    public String getUniqueID(){
        return Settings.Secure.getString(mContext.getContentResolver(), Settings.System.ANDROID_ID);
    }

Android IDについては色々苦労ポイントがありますが、気になる方は以下を読んでみてください。

ファイルストレージへの書き込み

ファイルに追加書き込みします。CSV形式で書き込みをしています*11

    public boolean write(String start_time, String qr_code, Integer cnt, Integer chk) {

        OutputStream out_stream;
        StringBuilder buf = new StringBuilder();
        buf.append(getTime());
        buf.append(", ");
        buf.append(qr_code);
        buf.append(", ");
        buf.append(cnt.toString());
        buf.append("\n");
 
       try {
            out_stream = new FileOutputStream(new File(file_name), true);
            PrintWriter writer = new PrintWriter(new OutputStreamWriter(out_stream, "UTF-8"));
            //追記する
            writer.append(buf.toString());
            writer.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return true;
    }

Android端末を接続した状態でAndroid StudioでDevice File Explorerをクリックすると、図のようにログを見つけられます。 ここから直接PCに取り込むことも可能です。

f:id:optim-tech:20191217151234p:plain

ハードウェア選定

約40か所のブースに設置するので高価な端末をホイホイ用意したら大赤字です。 今回はFPSも1~3FPS程度あれば十分なので、比較的安価に入手できる AQUOS 702SHを採用しました!
主なスペックは以下の通りです。

  • 液晶:5in IGZO IPS液晶(1920×1080)
  • OS:Android 8.0
  • CPU:MSM8937 1.4GHz/1.1GHz
  • メモリ:3 GB
  • ストレージ:32 GB
  • カメラ:約1310万画素/CMOS

耐久テスト

AI Markerは少なくとも半日安定して動作する必要があるので、耐久テストを実施して問題がないか確認する必要があります。 今回はAI Markerの耐久試験の様子を撮影してみました。

  • おもちゃの回転寿司レーン(回転寿司)にQRコードを貼り付けて来場者を模擬
  • 会場は様々な光源が予想されるので、(手動で)ライトを点滅させて動作に問題がないか確認
  • QRコードが認識されると、赤枠で表示
  • 回転寿司の電池が切れるまで(10時間くらい?)動作

さて、耐久テストもバッチリだったのであとは本番を迎えるだけですね。

いざ本番

本番は大きなトラブルなく無事に検出できましたが、いくつかトラブルや課題が発生したので振り返っておきます。

電源抜けでバッテリー切れ

会場の写真や耐久テストにも映り込んでいるのですが、AI Marker(ML Kit)は電池消費が激しいため充電し続ける必要があります。 しかし、とあるブースで充電ケーブルが抜けておりAI Markerが短期間停止しました。バッテリーが少なくなったらアラートを出す仕組みが必要ですね。

QRコードが服に隠れて認識できない

QRコードは2種類用意していて、来場者の方々には以下のルールで付けていただく想定でした。

  • 胸ポケットのある方は右の大きいQRコードを胸ポケットに
  • 胸ポケットのない方は名刺サイズのQRコードを胸の付近に

f:id:optim-tech:20191218131619j:plain:w360

これは実際に運用して気が付いたのですが、ジャケットの襟や胸ポケットにQRコードが隠れる事例が散見されました。 QRコードは誤り訂正があるので一部の汚れ等には強いですが、一定の領域が隠れてしまうとダメでした。
これは我々の考慮不足なので、QRコードの余白を大きくするなど製品版では改善していきます。

動作確認が大変

当日は私が1台ずつ設置していたのですが、Android Studioでデバッグしながら動作確認していました。 クラウドにデータをUPしたり、QRコードを認識するとランプが点灯したりも考えたのですが、間に合いませんでした。 当然ながら、製品版では対策が必要になります。

ログデータ解析と成果物

さてさて、本番も無事に終わり大量のログデータが収集できましたが、ここからがAI Markerの本領発揮です。 ということでこのログデータを使用して来場者の方々へお礼メールを送り、さらに各ブースの来場者数の傾向をみていきます。

お礼メール作成

約40台のAI Markerを活用することで、来場者の方がどんなブースにどんな順番でどれくらい滞在したのか分析できます。トラッキングですね。このトラッキング情報をもとに、「こういうのも興味あるんじゃないかな」という予測もしていきたいですね。 OPTiM INNOVATION 2019では、その結果を来場者の方にメールで配信しました*12。 メールはこのような形で送信されました。

オプティム 太郎 様

この度は、OPTiM INNOVATION 2019にご来場いただきありがとうございました。
OPTiM AI Marker により、AIが オプティム 太郎 様 の立ち寄られた展示を分析いたしました。
対象の展示ブースの資料をお送りいたしますのでぜひご覧ください。

お立ち寄りいただいたブース

医療系ソリューション
  AMIAS 2019-10-25 10:41:47から 228秒ご滞在 [PDF] [Web]
  OPTiM Doctor Eye 2019-10-25 10:45:37から 38秒ご滞在 [PDF] [Web]
農業系ソリューション
  革新的技術開発事業 2019-10-25 10:58:03から 53秒ご滞在 [PDF] [Web]
  災害支援ソリューション 2019-10-25 10:59:52から 50秒ご滞在 [PDF] [Web]
  スマート農業​ プロフェッショナルサービス​ 2019-10-25 11:00:33から 76秒ご滞在 [PDF] [Web]
  DRONE CONNECT 2019-10-25 11:01:30から 77秒ご滞在 [PDF] [Web]
  SMART AGRI 2019-10-25 11:02:33から 12秒ご滞在 [PDF] [Web]
OPTiM AI Industry
  for 銀行(佐賀銀行) 2019-10-25 10:15:54から 216秒ご滞在 [PDF] [PDF]
  for 駅(TOA株式会社) 2019-10-25 10:18:57から 176秒ご滞在 [PDF] [Web]
AIサービス
  OPTiM AI Camera 2019-10-25 10:14:39から 34秒ご滞在 [Web]
  OPTiM AI Research 2019-10-25 10:30:19から 216秒ご滞在 [PDF] [Web]
  OPTiM AI Signage 2019-10-25 10:37:10から 154秒ご滞在 [PDF] [Web]
プラットフォーム
  OPTiM Cloud IoT OS 2019-10-25 10:39:59から 48秒ご滞在 [PDF] [Web]
その他の資料は こちら からご覧いただけます。 今後ともオプティムをお願いいたします。 このメールは、OPTiM INNOVATION 2019ご来場いただいた方にお送りしています。 ---以下略---

このようにして、全自動で来場者の方の一人一人に最適化されたメールを送れるのはAI Markerの強みです。

ブースの分析

AI Marker では、来場者ベースのトラッキングだけでなく、ブース単位での集計も可能です。 OPTiM INNOVATION 2019のブースごとの来場者数はこのようになっています*13。 他にも、時系列でログデータが残っているので各ブースの時系列の来場者推移も可視化できます。

f:id:optim-tech:20191218143313p:plain:w360

現在はリアルタイム解析まではできていませんが、それができればAI Markerの可能性はさらに広がります。

以上でAI Markerの紹介は終わりますが、みなさんAI Markerの可能性を感じることができたでしょうか?OPTiM INNOVATION 2019での事例はほんの一例です。みなさんのアイデア次第でAI Markerは化けますので、是非一緒にイノベーションを起こしていきましょう!

最後に

OPTiMでは、業種職種問わずチャレンジャーなエンジニアを募集しています。体力系エンジニアの方々は是非一緒に皇居を走りましょう。

*1:Type-Cの不具合は解消されていたので、早速ポチりました

*2:QRコードはデンソーウェーブの登録商標です

*3:イベント当日まで1か月程度しかない

*4:記事公開時(19/12/24)にて確認

*5:AI Marker開発時点では白画面でタイトルもありませんでしたが、最近のバージョンはUIが進化していますね

*6:初めて実行する場合は権限を聞かれるかもしれません

*7:最近クランチにハマっています。サクサク食べられるので食べ過ぎには注意しましょう。

*8:みんな大好きカロリーメイト(チョコレート)ですね。私の朝ごはんです

*9:今後も採用するかどうかは未定です

*10:Java歴1か月なのでお手柔らかにお願いします

*11:本来であれば暗号化等もしっかりやるべきですが、α版なので

*12:データの取得が上手くいった方にはメールが届いていると思います

*13:一部ボカしています