AIをARに応用するぞ会 → (第3回) ~スマホでAI作動2~
こんにちは。
開発メンバーのKです。
GWは田植えをしました。
体がなまっていたので、ひどい筋肉痛になりました。
全自動で田植えをする機械が欲しい。
さて今回は、前回に引き続きスマホでAIを動かすことにチャレンジしました。
以下、目次です。
- 1. 前回詰まったところ
- 2. MappedByteBuffer形式でうまくreadできた
- 3. activityを取得してcontextに入れる
- 4. Android Studioでファイルをリードするときはassetsフォルダを使う
- 5. リードはできたけどまた壁が
1. 前回詰まったところ
前回、Android上でClassificationするために、Android studio上のjavaでTensorflow liteを動かそうとしました。
しかし、学習済みモデルをうまくreadできてない状態でした。
(我々はjava初心者なので、わからないことだらけで大変です...)
↓前回のブログ
tottorisnow33.hatenablog.com
2. MappedByteBuffer形式でうまくreadできた
tensorflow liteの公式ページを見ると、モデルのリード及び実行は Interpreter クラスを使用するそうです。
リード方法は、Fileクラスの変数を入れるか、MappedByteBufferクラスの変数を入れるかのどちらかです。
https://www.tensorflow.org/lite/guide/inference?hl=ja
ネットで具体的にリードのやり方を調べていると、MappedByteBufferクラスを使ったやり方を見つけました。
以下、その見つけたページです。大変助かりました。
note.com
MappedByteBuffer形式でファイルを取得するのに、
このページの
private MappedByteBuffer loadModel(String modelPath)
関数を使わせていただきました。
実際には、この関数の引数に
Context context
追加して、関数内のthis.contextを、引数でもらったcontextになるように書き換えました。
そのうえで、以下のように関数を呼び出してMappedByteBufferを取得して、
それからInterpreterのインスタンス化をしました。
String ModelPath = "model_img_recog_ramen_pan_bn.tflite"; Context context = MainActivity.this; MappedByteBuffer MyModel = loadModel(context, ModelPath); Interpreter interpreter = new Interpreter(MyModel)
普通、リードをするだけなら、ファイルパスを指定して、適当なリード関数を使えばいいんじゃない?と思っていましたが、
そんな簡単ではありませんでした。
ここでポイントとなるのは、
- activityを取得してcontextに入れる(3節)
- Android Studioでファイルをリードするときはassetsフォルダを使う(4節)
ということです。
3. activityを取得してcontextに入れる
そもそもcontextとは(まだよく理解してないですが)、アプリケーション周りのインターフェースの情報を使うのに利用するクラスのようです。
以下のページが参考になるかと思います。
developer.android.com
qiita.com
そのcontextにActivityを代入するために、
MainActivity.this
を参照しました。
MainActivityは、自分たちがモデルファイルをリードしようとしているクラスのクラス名です。
4. Android Studioでファイルをリードするときはassetsフォルダを使う
自分たちは最初、FileクラスをInterpreterの引数にしてリードしようとしました。
しかし、Fileのexsists関数で読み込めているかを確認すると、Falseが帰ってきてしまいました。
つまり、Interpreter クラス以前に、File クラスでのリードができていなかったのです。
これの原因はまだよくわかっていなのですが、おそらく、直接ファイルパスを指定してリードしようとしたのがダメなのかと思います。
本来、Android studioでファイルをリードするときは、assetsフォルダに入れてそこから決まった手順でリードするべきなようです。
assetsを使ってリードする方法はいくつかあるようなのですが、
今回自分たちはcontextを使ってリードしています。
実際にやった手順は以下の通りです。
(1) 事前に、リードしたいファイルをassetsフォルダに入れる。
(2) ソース上で、activityを取得してcontextに入れる(3節)
(3) 以下のソースでAssetFileDescriptorを取得
context.getAssets().openFd("リードしたいファイル名")
(3)以降の手順は先ほど紹介した以下のページの
private MappedByteBuffer loadModel(String modelPath)
関数を参照してください。
note.com
以上の手順でassetsフォルダのファイルを、
MappedByteBuffer 形式でリードすることができます。
5. リードはできたけどまた壁が
以上でtffileをリードすることはできたようなので、
さっそくinterpreter.runを実行しました。
すると以下のようなエラーが、、、
E/libc: Access denied finding property "ro.hardware.chipname" A/libc: Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x0 in tid 12027 (pplication_test), pid 12027 (pplication_test)
ハードを使うのに何か必要な手順でもあるのでしょうか?
また、Interpreterをインスタンス化するソースで、下のような感じでnew の後のInterpreterに謎の横線が出ました。(ちょっと見づらいですが)
Interpreter interpreter = new Interpreter(MyModel)
Android studio上で勝手にやってくれていることのようなのですが、なんでこうなっているかさっぱり。
問題あるのかないのか良くわかっていません。
次回はこれらの解決から始めることになりそうです。