茨城エンジニアのPython開発日記

茨城のITベンチャー企業ではたらく2年目エンジニア。Pythonで色々なものを作成中。

AIをARに応用するぞ会 → (第12回) ~tfliteをリードして推論~


ブログから記事を見つけたい場合はこちら

ブログ地図 - 茨城エンジニアのPython開発日記



こんにちは。
開発メンバーのKです。

早いもので2021年ももうすぐ終わりですね。
最近、ネットフリックスでソードアート・オンラインを一通り見直しました。
SAOの世界では2022年にキリト君たちがダイブして出られなくなったわけですが、僕らの世界は2022年にSAOのようなVRMMORPGが出るのでしょうか。。。


さて、今回はカメラで取得した画像をtflite形式のモデルに入れて識別してみました。


以下、目次です。

0. 前回まで

↓前回のブログ
tottorisnow33.hatenablog.com

前回までは android studio上で、webカメラで取得した画像をOpen CVを使ってプレビューするところまで行きました。
次はtensorflow liteを使うぞ! というところで、android studioが4.1以上じゃないといけないことが発覚し、 4.0を入れていた我々はandroid studio 4.0のアンインストールから始めました。


1. tensorflow liteを使えるAndroid studioのバージョン

tensorflow liteを使うためには、android studio 4.1以上が必要だそうです。
www.tensorflow.org

しかし前回、opencvを使おうとしたら、android studio (arctic fox) のバグでインポートできなかったので、android studioバージョンを4.0まで下げていました。

opencvも使いたいし、tensorflow liteも使いたいので、今回 android studio 4.1.3を導入しました。


2. tfliteファイルのリード

以前、ラーメンかパンケーキかを分類するためのモデルをtensorflowで学習させました。
論文読んでAIつくるぞ会(第9.5回) ~ResNetを作ってみた~ - 茨城エンジニアのPython開発日記

それから、そのモデルをtflite形式に変換しました。
AIをARに応用するぞ会 → (第2回) ~スマホでAI作動1~ - 茨城エンジニアのPython開発日記

そして、tfliteをandroid studioでリードさせて、推論させることもやりました。
AIをARに応用するぞ会 → (第5回) ~スマホでAI作動4~ - 茨城エンジニアのPython開発日記


今回はこの第5回の時のソースコードを、前回のカメラ画像を取得してopencvで利用するソースコードに入れ込みました。
(全体のソースコードはまだ汚いので、奇麗にしたら次回以降のブログでアップします。)

3. Mat型の画素アクセス

カメラで取得した画像はMat型で、一方tfliteでリードした識別器への入力はfloatの配列です。そのため、Mat型の画素ごとにアクセスして、rgb値をfloatの配列に入れました。

/* IMG_HEIGHT=224, IMG_WIDTH=224 */
float[][][][] testImg = new float[1][IMG_HEIGHT][IMG_WIDTH][3];
for (int i = 0; i < IMG_WIDTH; i++) {
    for (int j = 0; j < IMG_HEIGHT; j++) {
        double[] value = matInput.get(j, i);

        testImg[0][i][j][0] = (float) value[2] / 255.0f;
        testImg[0][i][j][1] = (float) value[1] / 255.0f;
        testImg[0][i][j][2] = (float) value[0] / 255.0f;
    }
}

matInputにカメラで取得した画像の情報が入っていて、get() 関数で画素の位置を指定して取得しています。
get関数の戻り値はvalue配列に入れています。このとき、カメラで取得した画像はRGBのため、valueには指定した画素のrgb値が入ります。
それから、識別器に入力する testImg にr,g,bをそれぞれ255で正規化して格納しています。


4. 実行結果

実行結果は以下の通りです。

使っているモデルはラーメンかパンケーキかを識別するための2クラス分類です。確率が高いほうが表示されます。
↑のリンクではパンケーキの画像をカメラで移しているので、パンケーキと言ってほしいところですが、、なぜかラーメンと言っています。

おそらくですが、識別器に入力している画像に何らかのバグがあって、識別結果がおかしいのかなと思います。
もしかすると、Mat型がfloatの配列 に入れるときに、get()関数のi, jが逆とかr,g,b値の順番が違うのかも。。

5. 次回やること

とりあえず、ついに形になってきたのでうれしいです!
とはいえ、まだ識別器の結果がおかしいので、次回はデバッグをやりたいと思います。